29

Will finally block execute? if I pass exit; ?

procedure someProc;
begin
    Try
      Exit;
    finally
     do_something;
    end;
end;
menjaraz
  • 7,551
  • 4
  • 41
  • 81
jmp
  • 2,456
  • 3
  • 30
  • 47
  • 2
    Side note: `while True do try Exit; finally Continue; end;` will not compile - see [Fun with Infinite Loops in Delphi and Java](http://mikejustin.wordpress.com/2008/07/13/fun-with-infinite-loops-in-delphi-and-java/) – mjn Dec 23 '11 at 08:13

4 Answers4

39

Yes, finally blocks always execute, even if you call Exit somewhere. They wouldn't be worth much if they weren't always executed.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
30

The finally clause will always be executed, unless the executing thread enters a non-terminating loop, blocks indefinitely or is terminated abnormally, whilst executing the try clause.

The pertinent documentation states (emphasis mine):

The syntax of a try...finally statement is

try 
  statementList1
finally
  statementList2 
end 

where each statementList is a sequence of statements delimited by semicolons.

The try...finally statement executes the statements in statementList1 (the try clause). If statementList1 finishes without raising exceptions, statementList2 (the finally clause) is executed. If an exception is raised during execution of statementList1, control is transferred to statementList2; once statementList2 finishes executing, the exception is re-raised. If a call to the Exit, Break, or Continue procedure causes control to leave statementList1, statementList2 is automatically executed. Thus the finally clause is always executed, regardless of how the try clause terminates.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
15

A quick test app could have answered this question really quickly.

program TestFinally;

{$APPTYPE CONSOLE}

uses
  SysUtils;

begin
  try
    WriteLn('Before exiting');
    Exit;
  finally
    WriteLine('In finally. If you see this, it was written after "Exit" was called');
    ReadLn;
  end;
end.
Ken White
  • 123,280
  • 14
  • 225
  • 444
12

For the sake of completeness - finally block will not execute if the process or thread executing the try..finally block is terminated with TerminateProcess/TerminateThread.

For example, finally block will not be executed in the code below.

o := TObject.Create;
try
  TerminateThread(GetCurrentThread, 0);
finally
  o.Free;
end;
gabr
  • 26,580
  • 9
  • 75
  • 141
  • Did I miss that in my answer? Maybe I should have said terminate *thread* abnormally rather than program. – David Heffernan Dec 23 '11 at 08:41
  • You're right, you said that. Feel free to merge my example in your answer, then I'll delete mine. – gabr Dec 23 '11 at 09:28
  • 2
    I edited my text to make it a little more complete. Your answer covers that particular aspect in depth and I think merging your example into my answer would detract from the main point which is the documentation quote. Thanks and +1. – David Heffernan Dec 23 '11 at 09:31