Recent

Author Topic: [SOLVED] How to know if finally is reached because exception?  (Read 4533 times)

lucamar

  • Hero Member
  • *****
  • Posts: 3074
[SOLVED] How to know if finally is reached because exception?
« on: December 22, 2018, 10:54:55 pm »
In a try...finally block, is there any way to know if the finally is being executed because an exception? I mean, without recurring to an inner try..except or to setting a flag.

In other "words", how to do this:
Code: Pascal  [Select][+][-]
  1. GetSomeResource;
  2. try
  3.   DoSomething; {may raise exception!}
  4.   {Note: DoSomething is a placeholder for "lots of lines",
  5.     not strictly a function call.}
  6. finally
  7.   if ExceptionHappened then
  8.     TakeHeroicMeasures
  9.   else
  10.     TakeNormalMeasures;
  11.   FreeSomeResource;
  12. end;

I know it may sound strange but I need to know if it is possible, although I suppose it isn't. But if anyone can surprise me, please, go ahead!
« Last Edit: December 23, 2018, 02:59:30 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

dsiders

  • Sr. Member
  • ****
  • Posts: 378
Re: How to know if finally is reached because exception?
« Reply #1 on: December 22, 2018, 11:20:58 pm »
In a try...finally block, is there any way to know if the finally is being executed because an exception? I mean, without recurring to an inner try..except or to setting a flag.

In other "words", how to do this:
Code: Pascal  [Select][+][-]
  1. GetSomeResource;
  2. try
  3.   DoSomething; {may raise exception!}
  4.   {Note: DoSomething is a placeholder for "lots of lines",
  5.     not strictly a function call.}
  6. finally
  7.   if ExceptionHappened then
  8.     TakeHeroicMeasures
  9.   else
  10.     TakeNormalMeasures;
  11.   FreeSomeResource;
  12. end;

I know it may sound strange but I need to know if it is possible, although I suppose it isn't. But if anyone can surprise me, please, go ahead!

If DoSomething can raise AND handle an exception, I would make it a Boolean function that indicates that an ExceptionHappened (and was handled) on exit. Then:

Code: [Select]
ExceptionHappened := DoSomething;

Hmm... should have read the comments closer. Disregard.
« Last Edit: December 22, 2018, 11:22:57 pm by dsiders »
Lazarus 2.1 (SVN) / FPC 3.0.4 / FPC 3.2.0 / x86-win64 / Windows 8.1

wp

  • Hero Member
  • *****
  • Posts: 7619
Re: How to know if finally is reached because exception?
« Reply #2 on: December 22, 2018, 11:31:47 pm »
In a try...finally block, is there any way to know if the finally is being executed because an exception?
Initiate a boolean variable to false and set it to true in the line immediately before the "finally". If it is still false inside the "finally" block then an exception must have occured because otherwise the variable would have been set to true:
Code: Pascal  [Select][+][-]
  1. var
  2.   ok: Boolean;
  3. ...
  4.   ok := false;
  5.   try
  6.     ... do something ...
  7.     ok := true;
  8.   finally
  9.     if not ok then Writeln('An exception has happened');
  10.   end;
But I don't understand why this is important to you. Normally the "finally" block should not care about exception or not, it should just release resources that were acquired before the "try"
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

lucamar

  • Hero Member
  • *****
  • Posts: 3074
Re: How to know if finally is reached because exception?
« Reply #3 on: December 22, 2018, 11:44:25 pm »
If DoSomething can raise AND handle an exception, I would make it a Boolean function that indicates that an ExceptionHappened (and was handled) on exit. Then:
Code: [Select]
ExceptionHappened := DoSomething;

That "DoSomething" is just a placeholder; imagine instead a score of lines doing each its thing which may or may not raise an exception. Besides, as stated, I don't want to use a flag (which is trivial, if needed) but capture the exceptional state in the finally section ... if at all possible, that is. :)

Initiate a boolean variable to false and set it to true in the line immediately before the "finally".
[...]
But I don't understand why this is important to you. [...]

Yeah, as I said above using a flag (or try...except) is trivial; that's not what I wanted.

The "why" is not relevant: you can call it "curiosity" if you want ;)

ETA

To make it clearer: I already know (most of) the conventional ways of dealing with this. What I want to know is if the "unconventional" way is possible some way.
« Last Edit: December 22, 2018, 11:46:17 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

wp

  • Hero Member
  • *****
  • Posts: 7619
Re: How to know if finally is reached because exception?
« Reply #4 on: December 23, 2018, 12:41:34 am »
Yeah, as I said above using a flag is trivial; that's not what I wanted.
Sorry, I was not reading carefully enough - as usual...
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

HeavyUser

  • Sr. Member
  • ****
  • Posts: 310
Re: How to know if finally is reached because exception?
« Reply #5 on: December 23, 2018, 01:05:36 am »
In a try...finally block, is there any way to know if the finally is being executed because an exception? I mean, without recurring to an inner try..except or to setting a flag.

In other "words", how to do this:
Code: Pascal  [Select][+][-]
  1. GetSomeResource;
  2. try
  3.   DoSomething; {may raise exception!}
  4.   {Note: DoSomething is a placeholder for "lots of lines",
  5.     not strictly a function call.}
  6. finally
  7.   if ExceptionHappened then
  8.     TakeHeroicMeasures
  9.   else
  10.     TakeNormalMeasures;
  11.   FreeSomeResource;
  12. end;

I know it may sound strange but I need to know if it is possible, although I suppose it isn't. But if anyone can surprise me, please, go ahead!
I would look for a global exception function or object or stuck rewind pointer etc, probably in the unit that initializes the exceptions (sysutils?) or the forms unit that handles the application exceptions. I think that the objfpc mode either already supports or it is in testing the try..except..finally..end syntax, which I prefer from the existing choices.

lucamar

  • Hero Member
  • *****
  • Posts: 3074
Re: How to know if finally is reached because exception?
« Reply #6 on: December 23, 2018, 01:41:58 am »
I would look for a global exception function or object or stuck rewind pointer etc, probably in the unit that initializes the exceptions (sysutils?) or the forms unit that handles the application exceptions.

I shall keep looking. So far, I've found gazillion ways to cope with exceptions but nothing that tells you you're inside an exception frame. You know you are when you're responding to one, but when not (directly)?

Quote
I think that the objfpc mode either already supports or it is in testing the try..except..finally..end syntax, which I prefer from the existing choices.

That's rather nice. I always though it sounds disrespectful to the program having to use "try {really} try ... except ...finally" ;D
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

jamie

  • Hero Member
  • *****
  • Posts: 3637
Re: How to know if finally is reached because exception?
« Reply #7 on: December 23, 2018, 05:11:08 am »
If you are trying to debug a number of steps between the Try and Finally, create a variable, set it to 0 before
you enter the TRY..
  Increment this variable after each step.

 So you'll have Step 1, Step 2 code, etc.

 When FINALLY comes, you can test the variable then..

 This is what I do in cases like this...

 P.S.
   if memory servers I think someone was telling me that even if you  use the EXIT within the try, it'll exit to
FINALLY instead...

 In any case, FINALLY should always be reached.
« Last Edit: December 23, 2018, 05:12:42 am by jamie »
The only true wisdom is knowing you know nothing

ASerge

  • Hero Member
  • *****
  • Posts: 1678
Re: How to know if finally is reached because exception?
« Reply #8 on: December 23, 2018, 05:33:30 am »
In a try...finally block, is there any way to know if the finally is being executed because an exception? I mean, without recurring to an inner try..except or to setting a flag.
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$APPTYPE CONSOLE}
  3.  
  4. uses SysUtils;
  5.  
  6. var
  7.   X: TObject;
  8. begin
  9.   try
  10.     X := TObject.Create;
  11.     try
  12.       Abort;
  13.     finally
  14.       X.Free;
  15.       if Assigned(ExceptObject) then
  16.         Writeln('Exception raised')
  17.       else
  18.         Writeln('Normal finalization')
  19.     end;
  20.   except
  21.     on E: Exception do
  22.       Writeln('Error: ', E.Message);
  23.   end;
  24.   Readln;
  25. end.

lucamar

  • Hero Member
  • *****
  • Posts: 3074
Re: How to know if finally is reached because exception?
« Reply #9 on: December 23, 2018, 02:58:18 pm »
Yes, ASerge!!! That's exactly what I wanted!!! Many thanks!
:D

Now I'll have to investigate ExceptObject by myself :)
« Last Edit: December 23, 2018, 03:00:37 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 820
    • Lebeau Software
Re: How to know if finally is reached because exception?
« Reply #10 on: December 28, 2018, 12:57:54 am »
Now I'll have to investigate ExceptObject by myself :)

Note that ExceptObject() only works if a TObject-derived object is raised, such as a Sysutils.Exception or descendant.  Which is USUALLY the case, but not always.  Also look at ExceptAddr(), too.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: How to know if finally is reached because exception?
« Reply #11 on: December 28, 2018, 02:14:05 am »
Note that ExceptObject() only works if a TObject-derived object is raised, such as a Sysutils.Exception or descendant.  Which is USUALLY the case, but not always.  Also look at ExceptAddr(), too.

From the code of both functions ExceptObject and ExceptAddr, RaiseList is a better option. Both functions start with:
Code: Pascal  [Select][+][-]
  1. begin
  2.   If RaiseList=Nil then
  3.     Result:=Nil

lucamar

  • Hero Member
  • *****
  • Posts: 3074
Re: [SOLVED] How to know if finally is reached because exception?
« Reply #12 on: December 28, 2018, 11:04:33 am »
From "I don't think it is possible" to "Wow, so many options!" :)

Thanks everyone, you guys rock!
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2248
  • Compiler Developer
Re: How to know if finally is reached because exception?
« Reply #13 on: December 28, 2018, 04:58:46 pm »
Now I'll have to investigate ExceptObject by myself :)

Note that ExceptObject() only works if a TObject-derived object is raised, such as a Sysutils.Exception or descendant.  Which is USUALLY the case, but not always.  Also look at ExceptAddr(), too.
Ehm... in Object Pascal every exception is a descendant of TObject. However not every exception needs to be a descendant of SysUtils.Exception. So ExceptObject will always be assigned if an exception occurred (and has not yet been handled by an exception handler).

lucamar

  • Hero Member
  • *****
  • Posts: 3074
Re: [SOLVED] How to know if finally is reached because exception?
« Reply #14 on: December 28, 2018, 06:17:36 pm »
I (finally) wrote a little test: just a form with a button and an exception-raising procedure wich gets called in the button's OnClick handler. Relevant code:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.RunIfYouDare(const WithException: Boolean);
  2. { Let's check with and without a declared object.
  3.   Note: e: Exception is a field of the form }
  4. begin
  5.   if WithException then begin
  6.     e := Exception.Create('You dared!');
  7.     raise e;
  8.   end else
  9.     raise Exception.Create('You (almost) dared!');
  10. end;
  11.  
  12. procedure TForm1.Button1Click(Sender: TObject);
  13. begin
  14.   try
  15.     RunIfYouDare(); { Should raise an exception }
  16.   finally
  17.     if Assigned(ExceptObject) then
  18.       ShowMessage(
  19.           'As expected: an exception.' + LineEnding +
  20.           Format('She says: "%s"',[(ExceptObject as Exception).Message])
  21.         )
  22.     else
  23.       ShowMessage('The unexpected happened ... no exception!');
  24.   end;
  25. end;

Since the exception is not treated in anyway (no except block) it stays raised and bubbles up. The result(s) can be seen in the attached images.

Many thanks again to everyone.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018