Difference between revisions of "Raise"

From Lazarus wiki
Jump to navigationJump to search
(rework)
 
Line 1: Line 1:
 
{{Raise}}
 
{{Raise}}
  
 +
<syntaxhighlight lang="delphi" inline>Raise</syntaxhighlight> is an elementary [[statement]].
 +
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>.
  
Back to [[Reserved words]].
+
== 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”:
The [[Reserved word|reserved word]] <syntaxhighlight lang="pascal" inline>raise</syntaxhighlight> is used to explicitly throw an [[Exceptions|exception]].
+
<syntaxhighlight lang="delphi" line highlight="7">
The <syntaxhighlight lang="pascal" inline>raise</syntaxhighlight> statement stops normal execution  and transfers control to an exception handler.
+
program raiseDemo(input, output, stdErr);
 
+
{$modeSwitch class+}
== Summary ==
+
{$modeSwitch exceptions+}
 
+
type
The reserved word '''raise''':
+
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>
  
* belongs to [[object-oriented programming]];
+
== behavior ==
* causes an exception.
+
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">
== Example ==
+
program catchDemo(input, output, stdErr);
 
+
{$modeSwitch class+}
<syntaxhighlight lang="pascal">
+
{$modeSwitch exceptions+}
program Example1;
+
type
uses sysutils;
+
exception = class end;
 
 
function titleread(a_title:string):string;
 
var
 
  answer:string;
 
 
begin
 
begin
  writeln ( a_title);
+
try
  readln(answer);
+
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.
  
  if answer = '' then raise Exception.Create('Variable has no value');
+
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}}.
  result := answer;
+
If none is installed, the [[runtime error|run-time error]] 217 “Unhandled exception occurred” is generated.
end;
 
  
var
+
== application ==
  firstname,lastname:string;
+
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).
  
begin
+
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>]].
  firstname := titleread( 'Write your first name:');
 
  lastname := titleread( 'Write your last name:');
 
  writeln ('your name is ', firstname, ' ', lastname);
 
  readln;
 
end.
 
</syntaxhighlight>
 
  
== See also ==
+
== 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.
  
* [[Try| <syntaxhighlight lang="pascal" inline>try</syntaxhighlight>]]..[[Finally|<syntaxhighlight lang="pascal" inline>finally</syntaxhighlight>]] [[Block|block]].
+
== see also ==
* [[Try| <syntaxhighlight lang="pascal" inline>try</syntaxhighlight>]]..[[Except|<syntaxhighlight lang="pascal" inline>except</syntaxhighlight>]] block.
+
* [https://docwiki.embarcadero.com/RADStudio/Sydney/en/Exceptions_(Delphi) Exceptions (Delphi)]
* [[On| <syntaxhighlight lang="pascal" inline>on</syntaxhighlight>]]
 
 
* [[runtime error|run-time error]]
 
* [[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 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