Mega Code Archive

 
Categories / Delphi / Examples
 

Using TRY EXCEPT and TRY FINALLY statements

Title: Using TRY EXCEPT and TRY FINALLY statements Question: When writing applications that need to be fail-safe the TRY EXCEPT and TRY FINALLY statements are a very good way of avoiding and handling errors. Answer: bIntroduction/b When writing applications that are designated to run on their own in server environments or applications that need to be fail-safe the TRY EXCEPT END and TRY FINALLY END statements can be used to handle or avoid fatal errors. bException Handling Basics/b If an exception is caused somewhere in a code block the current executing of the block immediately ends, and jumps to the next EXCEPT or FINALLY statement immediately. If no exception handler is written then Delphi applications display an EXCEPTION dialog by default that usually says very little to the person using the program. The EXCEPT block is mainly used for handling the error situation. The FINALLY block is mainly used for cleanup code, since it is executed regardless of error or not. By combining these two blocks effective exception handlers can be written. The Delphi compiler also generates WARNINGS if certain code statements are placed in the wrong place outside/inside the blocks. uExample:/u Function CauseException(): Boolean; Var X : Integer; L : TStringList; Begin // Default result must be here or the compiler generates a warning Result := False; // We encapsulate everything in a TRY EXCEPT to make sure we // catch ALL exceptions { TRY EXCEPT BLOCK } bTry/b // Initialize variables (Zero them so we know they are NIL) L := NIL; { TRY FINALLY BLOCK } bTry/b // Create objects etc. L := TStringList.Create; // Do what we need to do X := 0; Inc(X); X := X DIV (X-1); // Causes DIVISION BY ZERO exception bFinally/b If Assigned(L) then FreeAndNil(L); bEnd;/b // Code after the FINALLY statement, that is executed // if NO exception occurred in the TRY FINALLY block // Note: Do not place any error prone code here. Result := True; bExcept/b On E:Exception do // This handles ALL exceptions Begin // Place Exception code here Result := False; End; bEnd;/b End; In the example above the code generates an EXCEPTION at the DIV statement, and will jump Directly to the FINALLY part of the TRY FINALLY block. After that the code again jumps to EXCEPTION part of the TRY EXCEPT block ! Please note the code flow, It skips the statements after the try finally block!!! If the code would not generate the error the TRY FINALLY block would still be executed (so the list is freed) but the code would NOT jump to the EXCEPT block. bAnother example with unhandeled and handeled execptions/b Below is another example with two procedures. One of them has exception handling, the other has not. As you can see when you run the code the GenError1 exception is logged in the timer and thus makes it hard to find. The GenError0 procedure exception is handeled inside the procedure so it is very easy to find. To test the example create a new application, add one Timer from the system tab and paste the code below. Also attach the timers OnTimer event to the pasted code. Procedure Log(S:String); Begin // Here you can log the exception in a file or database Beep; End; Procedure GenError0; Var L : TStringList; Begin Try L.Clear; Except On E:Exception do Log('GenError0: '+E.Message); End; End; Procedure GenError1; Var L : TStringList; Begin L.Clear; End; procedure TForm1.Timer1Timer(Sender: TObject); Var X : Integer; begin Try Timer1.Enabled := False; Try GenError0; // Handles it's own exception GenError1; // Causes exception, catched below Finally // This code is always executed Timer1.Enabled := True; End; ShowMessage('This will NEVER occur !!!'); Except On E:Exception do Log('TForm1.Timer1Timer: '+E.Message); End; end; bWhere to next ?/b If you want more information on exceptions check the Delphi Help File (search for "exception"), and also search the forums on the net for more information. As a pointer for further reading you can check the RAISE statement, that Re-Raises an exception so that it can be forwarded to another exception handler ... Enjoy !