Raise

From Lazarus wiki
Revision as of 15:58, 1 November 2022 by Kai Burghardt (talk | contribs) (rework)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Deutsch (de) English (en) suomi (fi)

Raise is an elementary statement. It explicitly throws an exception and transfers control to an exception handler. The raise statement is available and becomes a reserved word if {$modeSwitch exceptions+}.

syntax

Raise requires one tObject assignment-compatible pointer expression as an argument. Usually this pointer is a class instantiated “just for the occasion”:

1program raiseDemo(input, output, stdErr);
2{$modeSwitch class+}
3{$modeSwitch exceptions+}
4type
5	exception = class end;
6begin
7	raise exception.create;
8end.

After that an optional at-clause may override up to two pointer values:

7	raise exception.create at codePointer(123), pointer(456);

This is frequently used to make an exception appear to originate from outside some error-handling code, e. g. like this:

raise exception.create at get_caller_addr(get_frame), get_caller_frame(get_frame);

Furthermore, inside an except … on frame the caught exception can be “re-raised” by simply writing

raise;

behavior

Once an exception is “thrown” (in Java and other languages the statement reads throw) or “raised” (Delphi/FPC), the surrounding try frame (if any) is left immediately and the pointer (usually some kind of exception object) is passed up the hierarchy until there is a matching except … on clause:

program catchDemo(input, output, stdErr);
{$modeSwitch class+}
{$modeSwitch exceptions+}
type
	exception = class end;
begin
	try
		raise exception.create;
		writeLn('Never written.');
	except on e: exception do
		writeLn(stdErr, 'Caught exception');
		{ Caught exceptions are automatically destroyed }
		{ before program flow resumes. }
	end;
end.

Note, the text Never written. is never written. The program state, e. g. the values variables possessed before the exception was raised, is not saved, thus it is not possible to simply return to the place where the exception was originally raised.

If an exception is not caught, or if there is not any surrounding try  except end frame to begin with, the exception along with the values in the at-clause are passed to an exception handler. If none is installed, the run-time error 217 “Unhandled exception occurred” is generated.

application

Primarily, exceptions are raised to communicate some error condition that just occurred. It is recommended and common practice to use the sysUtils unit. The sysUtils unit installs a universal exception handler turning all RTEs into exceptions. This exception handler expects, and therefore it is recommended that all custom exception classes descend from the exception class (or possibly an appropriate descendant).

While exceptions are usually used to communicate a condition, yet sometimes raise is simply (ab‑)used as a OOP substitute for goto.

caveats

  • Raising an exception in an initialization section of a unit may not have the desired behavior, for instance, if sysUtils’ exception handler has not been installed yet.
  • Mulit-threaded applications need special care.

see also