17.1 The raise statement

The raise statement is as follows:

_________________________________________________________________________________________________________
Raise statement

--            -     ---------------------------------------------
  raise statement raise -               ------------------|
                       exception instance -exception address-|

--exception address -at- exception address------------------------------
                                     ,  address expression
___________________________________________________________________

This statement will raise an exception. If it is specified, the exception instance must be an initialized instance of any class, which is the raise type. The exception address and frame are optional. If they are not specified, the compiler will provide the address by itself. If the exception instance is omitted, then the current exception is re-raised. This construct can only be used in an exception handling block (see further).

Remark Control never returns after an exception block. The control is transferred to the first try...finally or try...except statement that is encountered when unwinding the stack. If no such statement is found, the Free Pascal Run-Time Library will generate a run-time error 217 (see also section 17.5, page 929). The exception address will be printed by the default exception handling routines.

As an example: The following division checks whether the denominator is zero, and if so, raises an exception of type EDivException

Type EDivException = Class(Exception);  
Function DoDiv (X,Y : Longint) : Integer;  
begin  
  If Y=0 then  
    Raise EDivException.Create ('Division by Zero would occur');  
  Result := X Div Y;  
end;

The class Exception is defined in the Sysutils unit of the rtl. (section 17.5, page 929)

Remark Although the Exception class is used as the base class for exceptions throughout the code, this is just an unwritten agreement: the class can be of any type, and need not be a descendent of the Exception class.

Of course, most code depends on the unwritten agreement that an exception class descends from Exception.

The following code shows how to omit an error reporting routine from the stack shown in the exception handler:

{$mode objfpc}  
uses sysutils;  
 
procedure error(Const msg : string);  
 
begin  
  raise exception.create(Msg) at  
    get_caller_addr(get_frame),  
    get_caller_frame(get_frame);  
end;  
 
procedure test2;  
 
begin  
  error('Error');  
end;  
 
begin  
  test2;  
end.

The program, when run, will show a backtrace as follows:

An unhandled exception occurred at $00000000004002D3 :  
Exception : Error  
  $00000000004002D3 line 15 of testme.pp  
  $00000000004002E6 line 19 of testme.pp

Line 15 is in procedure Test2, not in Error, which actually raised the exception.