Difference between revisions of "Raise"
(Created page with "{{Raise}} The reserved word <syntaxhighlight lang="pascal" enclose="none">raise</syntaxhighlight> is used to explicitly throw an exception. T...") |
(rework) |
||
(3 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{Raise}} | {{Raise}} | ||
− | + | <syntaxhighlight lang="delphi" inline>Raise</syntaxhighlight> is an elementary [[statement]]. | |
− | The <syntaxhighlight lang=" | + | It explicitly throws an [[Exceptions|exception]] and transfers control to an exception handler. |
+ | The <syntaxhighlight lang="delphi" inline>raise</syntaxhighlight> statement is available and becomes a [[Reserved word|reserved word]] if <syntaxhighlight lang="delphi" inline>{$modeSwitch exceptions+}</syntaxhighlight>. | ||
− | == | + | == syntax == |
+ | <syntaxhighlight lang="delphi" inline>Raise</syntaxhighlight> requires one [[TObject|<syntaxhighlight lang="delphi" inline>tObject</syntaxhighlight>]] assignment-compatible [[Pointer|pointer]] expression as an argument. | ||
+ | Usually this pointer is a [[Class|<syntaxhighlight lang="delphi" inline>class</syntaxhighlight>]] instantiated “just for the occasion”: | ||
+ | <syntaxhighlight lang="delphi" line highlight="7"> | ||
+ | program raiseDemo(input, output, stdErr); | ||
+ | {$modeSwitch class+} | ||
+ | {$modeSwitch exceptions+} | ||
+ | type | ||
+ | exception = class end; | ||
+ | begin | ||
+ | raise exception.create; | ||
+ | end. | ||
+ | </syntaxhighlight> | ||
+ | After that an optional <syntaxhighlight lang="delphi" inline>at</syntaxhighlight>-clause may override up to two pointer values: | ||
+ | <syntaxhighlight lang="delphi" line start="7" highlight="1"> | ||
+ | raise exception.create at codePointer(123), pointer(456); | ||
+ | </syntaxhighlight> | ||
+ | This is frequently used to make an exception appear to originate from outside some error-handling code, e. g. like this: | ||
+ | <syntaxhighlight lang="delphi"> | ||
+ | raise exception.create at get_caller_addr(get_frame), get_caller_frame(get_frame); | ||
+ | </syntaxhighlight> | ||
+ | Furthermore, ''inside'' an [[Except|<syntaxhighlight lang="delphi" inline>except</syntaxhighlight> … <syntaxhighlight lang="delphi" inline>on</syntaxhighlight>]] frame the caught exception can be “re-raised” by simply writing | ||
+ | <syntaxhighlight lang="delphi"> | ||
+ | raise; | ||
+ | </syntaxhighlight> | ||
− | + | == behavior == | |
− | + | Once an exception is “thrown” (in Java and other languages the statement reads <syntaxhighlight lang="java" inline>throw</syntaxhighlight>) or “raised” (Delphi/FPC), the surrounding [[Try|<syntaxhighlight lang="delphi" inline>try</syntaxhighlight>]] 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 [[On|<syntaxhighlight lang="delphi" inline>except</syntaxhighlight> … <syntaxhighlight lang="delphi" inline>on</syntaxhighlight>]] clause: | |
− | + | <syntaxhighlight lang="delphi" highlight="10"> | |
− | + | 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. | ||
+ | </syntaxhighlight> | ||
+ | Note, the text <syntaxhighlight lang="text" inline>Never written.</syntaxhighlight> 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. | ||
− | <syntaxhighlight lang=" | + | If an exception is ''not'' caught, or if there is not any surrounding <syntaxhighlight lang="delphi" inline>try … except end</syntaxhighlight> frame to begin with, the exception along with the values in the <syntaxhighlight lang="delphi" inline>at</syntaxhighlight>-clause are passed to an {{Doc|package=RTL|unit=system|identifier=exceptproc|text=exception handler}}. |
− | + | If none is installed, the [[runtime error|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|<syntaxhighlight lang="delphi" inline>sysUtils</syntaxhighlight> <syntaxhighlight lang="delphi" inline>unit</syntaxhighlight>]]. | |
− | + | The <syntaxhighlight lang="delphi" inline>sysUtils</syntaxhighlight> <syntaxhighlight lang="delphi" inline>unit</syntaxhighlight> {{Doc|package=RTL|unit=system|identfier=runtimeerrors|text=installs a universal exception handler}} turning all [[runtime error|RTEs]] into exceptions. | |
− | + | This exception handler expects, and therefore it is recommended that all custom exception classes descend from the {{Doc|package=RTL|unit=sysutils|identifier=exception|text=<syntaxhighlight lang="delphi" inline>exception</syntaxhighlight> <syntaxhighlight lang="delphi" inline>class</syntaxhighlight>}} (or possibly an appropriate descendant). | |
− | |||
− | + | While exceptions are usually used to ''communicate'' a condition, yet sometimes <syntaxhighlight lang="delphi" inline>raise</syntaxhighlight> is simply (ab‑)used as a [[object-oriented programming|OOP]] substitute for [[Goto|<syntaxhighlight lang="pascal" inline>goto</syntaxhighlight>]]. | |
− | |||
− | |||
− | + | == caveats == | |
− | + | * Raising an exception in an <syntaxhighlight lang="delphi" inline>initialization</syntaxhighlight> section of a <syntaxhighlight lang="delphi" inline>unit</syntaxhighlight> may not have the desired behavior, for instance, if <syntaxhighlight lang="delphi" inline>sysUtils</syntaxhighlight>’ exception handler has not been installed yet. | |
+ | * [[Multithreaded Application Tutorial|Mulit-threaded]] applications need special care. | ||
− | + | == see also == | |
− | + | * [https://docwiki.embarcadero.com/RADStudio/Sydney/en/Exceptions_(Delphi) Exceptions (Delphi)] | |
− | + | * [[runtime error|run-time error]] | |
− | |||
− | |||
− | |||
− |
Latest revision as of 16:58, 1 November 2022
│
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 aunit
may not have the desired behavior, for instance, ifsysUtils
’ exception handler has not been installed yet. - Mulit-threaded applications need special care.