Sign in Join
Wiki copytemporary

Exceptions: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-[[FPC|Free Pascal]] supports exceptions. Exceptions are useful for error handling and avoiding resource leaks. However, bear in mind that exceptions have a performance impact.
1+[[FPC|Free Pascal]] supports exceptions. Exceptions are useful for error handling and avoiding resource leaks. However, bear in mind that exceptions have a performance impact, i.e. exceptions are expensive (in processor time).
22
3-The official documentation is here: [Reference guide chapter 17](https://www.freepascal.org/docs-html/ref/refch17.html).
3+The official documentation is here: [Reference guide chapter 17](<https://www.freepascal.org/docs-html/ref/refch17.html>).
44
5-By default exceptions are disabled. You can opt in by using the [[Mode ObjFPC|ObjFPC]] or [[Mode Delphi|DELPHI]] [[Compiler Mode]], or adding -Sx to the [[Compiler|compiler]] [[Command-line interface|commandline]]. This enables the [[Try|try]], [[Raise|raise]], [[Except|except]], and [[Finally|finally]] [[Reserved word|reserved words]] for use in your own code, but it doesn't enable exception generation from the [[RTL]]. To enable the RTL to raise exceptions instead of generating [[runtime error|runtime errors]], use the SysUtils unit in your [[Program|program]].
5+By default exceptions are disabled. You can opt in by using the [[Mode ObjFPC|ObjFPC]] or [[Mode Delphi|DELPHI]] [[Compiler Mode]], or adding -Sx to the [[Compiler|compiler]] [[Command-line interface|commandline]]. This enables the [[Try|`try`]], [[Raise|`raise`]], [[Except|`except`]], and [[Finally|`finally`]] [[Reserved word|reserved words]] for use in your own code, but it doesn't enable exception generation from the [[RTL]]. To enable the RTL to raise exceptions instead of generating [[runtime error|runtime errors]], use the SysUtils unit in your [[Program|program]].
66
7-The base `Exception` [[Class|class]] is found in the [SysUtils](https://www.freepascal.org/docs-html/rtl/sysutils/exception.html) unit. All exceptions should preferably use this class or its descendants.
7+The base `Exception` [[Class|class]] is found in the [SysUtils](<https://www.freepascal.org/docs-html/rtl/sysutils/exception.html>) unit. All exceptions should preferably use this class or its descendants.
88
9-SysUtils automatically sets up a basic exception catcher, so any otherwise uncaught exception is displayed in human-readable form, as the program terminates. To generate readable callstacks from caught exceptions in your own code, without necessarily terminating the program, you can use SysUtils functions `ExceptAddr`, `ExceptFrames`, `ExceptFrameCount`, and `BackTraceStrFunc`.
9+SysUtils automatically sets up a basic exception catcher, so any otherwise uncaught exception is displayed in human-readable form, as the program terminates. To generate readable callstacks from caught exceptions in your own code, without necessarily terminating the program, you can use SysUtils functions `ExceptAddr`, `ExceptFrames`, `ExceptFrameCount`, and `BackTraceStrFunc`.
1010
11-While it is possible to raise an exception with any class descending from TObject, it is recommended to use Exception as the basis of exception class objects: the Exception class introduces properties to associate a message and a help context with the exception being raised. What is more, the SysUtils unit sets the necessary hooks to catch and display unhandled exceptions: in such cases, the message displayed to the end user, will be the message stored in the exception class.
11+
12+While it is possible to raise an exception with any class descending from TObject, it is recommended to use Exception as the basis of exception class objects: the Exception class introduces properties to associate a message and a help context with the exception being raised. What is more, the SysUtils unit sets the necessary hooks to catch and display unhandled exceptions: in such cases, the message displayed to the end user, will be the message stored in the exception class.
1213
13-On Windows with SEH using try … except-blocks (without using the SysUtils unit) will not behave as expected (from FPC 3.2.0 on). This due to a bug that will, in all probability be fixed at some stage. In the mean time, the very simple solution is to "use SysUtils".
14+On Windows with SEH using try … except-blocks (without using the SysUtils unit) will not behave as expected (from FPC 3.2.0 on). This due to a bug that will, in all probability be fixed at some stage. In the mean time, the very simple solution is to "use SysUtils".
1415
1516## Examples
1617
17-Note that Pascal uses different [[Keyword|keywords]] than some other languages: `raise` instead of `throw`, and `except` instead of `catch`. Also, as a compiler design choice, each `try`-block can pair with either an `except` or `finally` block, but not both at the same time. You'll need to nest `try`-blocks if you need `except` and `finally` protecting the same code.
18+Note that Pascal uses different [[Keyword|keywords]] than some other languages: `raise` instead of `throw`, and `except` instead of `catch`. Also, as a compiler design choice, each `try`-block can pair with either an `except` or `finally` block, but not both at the same time. You'll need to nest `try`-blocks if you need `except` and `finally` protecting the same code.
1819
1920### Error handling
20-
21-``` pascal
21+```
2222uses sysutils;
23-
24-begin
25- try
26- // Do something that might go wrong.
27- except
23+
2824 begin
29- // Try to recover or show the user an error message.
30- end;
31- end;
32-end.
25+ try
26+ // Do something that might go wrong.
27+ except
28+ begin
29+ // Try to recover or show the user an error message.
30+ end;
31+ end;
32+ end.
3333```
3434
3535### Cleaning up resources
36-
37-``` pascal
36+```
3837try
39- // Do something that might go wrong.
40-finally
41- // Clean-up code that is always called even if an exception was raised.
42-end;
38+ // Do something that might go wrong.
39+ finally
40+ // Clean-up code that is always called even if an exception was raised.
41+ end;
4342```
4443
4544### Exception leaking
4645
47-Finally-blocks don't destroy exception objects. Any exception that reaches the program's "end." will trigger a memory leak warning. An extra except block can be used to consume such exceptions. This is [Delphi-compatible](https://bugs.freepascal.org/view.php?id=33650).
48-
49-``` pascal
46+Finally-blocks don't destroy exception objects. Any exception that reaches the program's "end." will trigger a memory leak warning. An extra except block can be used to consume such exceptions. This is [Delphi-compatible](<https://bugs.freepascal.org/view.php?id=33650>).
47+```
5048begin
51- try
52- // Your main program, where an exception object is created.
53- finally
54- try
55- // Clean-up code.
56- except
57- end;
58- end;
59-end.
49+ try
50+ // Your main program, where an exception object is created.
51+ finally
52+ try
53+ // Clean-up code.
54+ except
55+ end;
56+ end;
57+ end.
6058```
6159
6260### Signalling problems
63-
64-``` pascal
61+```
6562raise Exception.Create('Helpful description of what went wrong');
6663```
6764
6865### Using specialised exception types to signal different problems
69-
70-``` pascal
66+```
7167type EMyLittleException = Class(Exception);
72-
73-begin
74- try
75- raise EMyLittleException.Create('Foo');
76- except
77- on E : EMyLittleException do writeln(E.Message);
78- on E : Exception do writeln('This is not my exception!');
79- else writeln('This is not an Exception-descendant at all!');
80- end;
81-end;
68+
69+ begin
70+ try
71+ raise EMyLittleException.Create('Foo');
72+ except
73+ on E : EMyLittleException do writeln(E.Message);
74+ on E : Exception do writeln('This is not my exception!');
75+ else writeln('This is not an Exception-descendant at all!');
76+ end;
77+ end;
8278```
8379
8480### Re-raising exceptions
85-
86-``` pascal
81+```
8782try
88- // Do something that might go wrong.
89-except
90- // Try to recover or show the user an error message.
91- if recoveredSuccessfully = FALSE then
92- raise;
93-end;
83+ // Do something that might go wrong.
84+ except
85+ // Try to recover or show the user an error message.
86+ if recoveredSuccessfully = FALSE then
87+ raise;
88+ end;
9489```
9590
91+
92+
9693## Exception classes
9794
98-SysUtils defines and raises many specific [exception classes](https://www.freepascal.org/docs-html/rtl/sysutils/index-4.html).
95+SysUtils defines and raises many specific [exception classes](<https://www.freepascal.org/docs-html/rtl/sysutils/index-4.html>).
9996
100-With SysUtils included in your program, and exceptions enabled, various [runtime errors](https://www.freepascal.org/docs-html/user/userap4.html) are changed into exceptions. Processor-level interrupts like SIGSEGV or SIGFPU, which normally translate to run-time errors, are also changed to exceptions. For example, run-time error 200 (division by zero) becomes EDivByZero or EZeroDivide, while run-time error 216 (a general protection fault) becomes EAccessViolation.
97+With SysUtils included in your program, and exceptions enabled, various [runtime errors](<https://www.freepascal.org/docs-html/user/userap4.html>) are changed into exceptions. Processor-level interrupts like SIGSEGV or SIGFPU, which normally translate to run-time errors, are also changed to exceptions. For example, run-time error 200 (division by zero) becomes EDivByZero or EZeroDivide, while run-time error 216 (a general protection fault) becomes EAccessViolation.
10198
99+
100+
102101## Best practice
103102
104-- Raise exceptions to signal that an operation could not be completed, where it normally should have succeeded.
105-- Do not use exceptions as part of expected control flow. Instead, add checks for common error conditions and return error values the old-fashioned way. For example, input parsing problems or file existence fails are usually not truly exceptional.
106-- But do raise an exception if it's critical that the error is noticed; programmers may forget to check for returned error values.
107-- Naming convention: Prefix exception class names with a capital E.
108-- Re-raise exceptions in `except`-blocks using `raise;` if you were unable to recover from the problem; this preserves the original exception's callstack.
109-- Be careful about using the catch-all base `Exception` class, since the underlying code or OS/filesystem might produce an unanticipated exception that slips through your exception handler, potentially corrupting the program state.
110-- When writing a unit or library, if exceptions are used at all, they should be documented clearly up front. This way the unit user knows what to expect.
111-- Keep exception handling away from code that needs to run as fast as possible.
103+ * Raise exceptions to signal that an operation could not be completed, where it normally should have succeeded.
104+ * Do not use exceptions as part of expected control flow. Instead, add checks for common error conditions and return error values the old-fashioned way. For example, input parsing problems or file existence fails are usually not truly exceptional.
105+ * But do raise an exception if it's critical that the error is noticed; programmers may forget to check for returned error values.
106+ * Naming convention: Prefix exception class names with a capital E.
107+ * Re-raise exceptions in `except`-blocks using `raise;` if you were unable to recover from the problem; this preserves the original exception's callstack.
108+ * Be careful about using the catch-all base `Exception` class, since the underlying code or OS/filesystem might produce an unanticipated exception that slips through your exception handler, potentially corrupting the program state.
109+ * When writing a unit or library, if exceptions are used at all, they should be documented clearly up front. This way the unit user knows what to expect.
110+ * Keep exception handling away from code that needs to run as fast as possible.
112111
112+
113+
113114## Performance
114115
115-Compiler optimisation levels don't make much difference. All exception blocks use a small amount of wrapper code that can't be optimised away. There are different ways for a compiler to produce exception code, with varying performance implications. As of FPC 3.0.4, the default exception mechanism uses the standard setjmp/longjmp style. FPC also supports OS-provided Structured Exception Handling; this is the default on Win64, and can be enabled on Win32 (recompile the compiler with `$define TEST_WIN32_SEH`). Other mechanisms may be added to FPC in the future.
116+Compiler optimisation levels don't make much difference. All exception blocks use a small amount of wrapper code that can't be optimised away. There are different ways for a compiler to produce exception code, with varying performance implications. As of FPC 3.0.4, the default exception mechanism uses the standard setjmp/longjmp style. FPC also supports OS-provided Structured Exception Handling; this is the default on Win64, and can be enabled on Win32 (recompile the compiler with `$define TEST_WIN32_SEH`). Other mechanisms may be added to FPC in the future.
116117
117-To get a better feel for what's going on, try writing a small test program and compiling it with the `-a` switch. This leaves behind a human-readable assembly file.
118+To get a better feel for what's going on, try writing a small test program and compiling it with the `-a` switch. This leaves behind a human-readable assembly file.
118119
119-Notes on the setjmp/longjmp method:
120+Notes on the setjmp/longjmp method:
120121
121-- `Try`-statements insert some extra address calculations, a stack push and pop, some direct jumps, and a conditional jump. This is the setup cost of an exception frame, even if no exception is raised.
122-- `Except`-statements insert the above, plus a push and pop, more direct jumps, and another conditional jump.
123-- `Finally`-statements add a pop and a conditional jump.
124-- `Raise`-statements create a string and pass control to FPC's exception raiser. The string creation itself can spawn an implicit exception frame for the function/method, due to dynamic string allocations, even if the `raise` is not executed. This is why in e.g. container types one often sees the `raise` moved to a separate local (private) procedure. This localises the exception frame to that procedure, so the performance hit is only taken if the procedure is called.
122+ * `Try`-statements insert some extra address calculations, a stack push and pop, some direct jumps, and a conditional jump. This is the setup cost of an exception frame, even if no exception is raised.
123+ * `Except`-statements insert the above, plus a push and pop, more direct jumps, and another conditional jump.
124+ * `Finally`-statements add a pop and a conditional jump.
125+ * `Raise`-statements create a string and pass control to FPC's exception raiser. The string creation itself can spawn an implicit exception frame for the function/method, due to dynamic string allocations, even if the `raise` is not executed. This is why in e.g. container types one often sees the `raise` moved to a separate local (private) procedure. This localises the exception frame to that procedure, so the performance hit is only taken if the procedure is called.
125126
126-Furthermore, generating a human-readable callstack from a raised exception involves time-consuming stack traversal and string manipulation.
127+Furthermore, generating a human-readable callstack from a raised exception involves time-consuming stack traversal and string manipulation.
127128
128-With all that said, outside of heavy processing code, the convenience of exceptions usually outweighs their performance impact. Don't feel bad about using them if it makes your code better.
129+With all that said, outside of heavy processing code, the convenience of exceptions usually outweighs their performance impact. Don't feel bad about using them if it makes your code better.
129130
130131## Further reading
131132
132133[[Logging exceptions]]
133134
134135[[Avoiding implicit try finally section]]
135136
136-[Exceptions vs Error codes](http://codenewsfast.com/cnf/article/0/permalink.art-ng53q201750) - a situation where exceptions might be a danger in some code (see middle of this page)
137+[Exceptions vs Error codes](<http://codenewsfast.com/cnf/article/0/permalink.art-ng53q201750>) \- a situation where exceptions might be a danger in some code (see middle of this page)
137138
138139---
139-*From the Free Pascal wiki, page "Exceptions", as it stood on 2023-12-22 after a change by Dbannon, 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).*
140+*From the Free Pascal wiki, page "Exceptions", as the Internet Archive kept it on 2025-05-08, last changed on 2024-10-10. 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).*

Back to history