Raise: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: Raise
| Old | New | Line | |
|---|---|---|---|
| 1 | + | `Raise` is an elementary [[statement]]. It explicitly throws an [[Exceptions|exception]] and transfers control to an exception handler. The `raise` statement is available and becomes a [[Reserved word|reserved word]] if `{$modeSwitch exceptions+}`. | |
| 2 | + | ||
| 3 | + | ## syntax | |
| 4 | + | ||
| 5 | + | `Raise` requires one [[TObject|tObject]] assignment-compatible [[Pointer|pointer]] expression as an argument. Usually this pointer is a [[Class|class]] instantiated “just for the occasion”: | |
| 6 | + | ||
| 7 | + | ```delphi | |
| 8 | + | program raiseDemo(input, output, stdErr); | |
| 9 | + | {$modeSwitch class+} | |
| 10 | + | {$modeSwitch exceptions+} | |
| 11 | + | type | |
| 12 | + | exception = class end; | |
| 13 | + | begin | |
| 14 | + | raise exception.create; | |
| 15 | + | end. | |
| 16 | + | ``` | |
| 17 | + | ||
| 18 | + | After that an optional `at`-clause may override up to two pointer values: | |
| 19 | + | ||
| 20 | + | ```delphi | |
| 21 | + | raise exception.create at codePointer(123), pointer(456); | |
| 22 | + | ``` | |
| 23 | + | ||
| 24 | + | This is frequently used to make an exception appear to originate from outside some error-handling code, e. g. like this: | |
| 25 | + | ||
| 26 | + | ```delphi | |
| 27 | + | raise exception.create at get_caller_addr(get_frame), get_caller_frame(get_frame); | |
| 28 | + | ``` | |
| 29 | + | ||
| 30 | + | Furthermore, *inside* an [[Except|except … on]] frame the caught exception can be “re-raised” by simply writing | |
| 31 | + | ||
| 32 | + | ```delphi | |
| 33 | + | raise; | |
| 34 | + | ``` | |
| 35 | + | ||
| 36 | + | ## behavior | |
| 37 | + | ||
| 38 | + | Once an exception is “thrown” (in Java and other languages the statement reads `throw`) or “raised” (Delphi/FPC), the surrounding [[Try|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 [[On|except … on]] clause: | |
| 39 | + | ||
| 40 | + | ```delphi | |
| 41 | + | program catchDemo(input, output, stdErr); | |
| 42 | + | {$modeSwitch class+} | |
| 43 | + | {$modeSwitch exceptions+} | |
| 44 | + | type | |
| 45 | + | exception = class end; | |
| 46 | + | begin | |
| 47 | + | try | |
| 48 | + | raise exception.create; | |
| 49 | + | writeLn('Never written.'); | |
| 50 | + | except on e: exception do | |
| 51 | + | writeLn(stdErr, 'Caught exception'); | |
| 52 | + | { Caught exceptions are automatically destroyed } | |
| 53 | + | { before program flow resumes. } | |
| 54 | + | end; | |
| 55 | + | end. | |
| 56 | + | ``` | |
| 57 | + | ||
| 58 | + | 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. | |
| 59 | + | ||
| 60 | + | 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](https://www.freepascal.org/docs-html/rtl/system/exceptproc.html). If none is installed, the [[runtime error|run-time error]] 217 “Unhandled exception occurred” is generated. | |
| 61 | + | ||
| 62 | + | ## application | |
| 63 | + | ||
| 64 | + | Primarily, exceptions are raised to communicate some error condition that just occurred. It is recommended and common practice to use the [[sysutils|sysUtils unit]]. The `sysUtils` `unit` [installs a universal exception handler](https://www.freepascal.org/docs-html/rtl/system/index.html) turning all [[runtime error|RTEs]] into exceptions. This exception handler expects, and therefore it is recommended that all custom exception classes descend from the [`exception` `class`](https://www.freepascal.org/docs-html/rtl/sysutils/exception.html) (or possibly an appropriate descendant). | |
| 65 | + | ||
| 66 | + | While exceptions are usually used to *communicate* a condition, yet sometimes `raise` is simply (ab‑)used as a [[object-oriented programming|OOP]] substitute for [[Goto|goto]]. | |
| 67 | + | ||
| 68 | + | ## caveats | |
| 69 | + | ||
| 70 | + | - 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. | |
| 71 | + | - [[Multithreaded Application Tutorial|Mulit-threaded]] applications need special care. | |
| 72 | + | ||
| 73 | + | ## see also | |
| 74 | + | ||
| 75 | + | - [Exceptions (Delphi)](https://docwiki.embarcadero.com/RADStudio/Sydney/en/Exceptions_(Delphi)) | |
| 76 | + | - [[runtime error|run-time error]] | |
| 77 | + | ||
| 78 | + | --- | |
| 79 | + | *From the Free Pascal wiki, page "Raise", as it stood on 2022-11-01 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
