3

Two very basic questions about exception handling in Delphi.

1) When to Try? My guess is that I don't need a Try clause around

  • strightforward code such as assignments, conditionals and loops
  • access to my VCL compnents

but that I do need to Try

  • database access
  • any thrid party components, as I don't know if they might raise an exception or not
  • anything which the help system shows can raise an exception

Did I miss anything?

2) Try ... Finally or Try ... Except ... or both? For years I have thought this to be an either / or choice, until @RRUZ answered one of my questions with some code which went

 try
    CoInitialize(nil);
    try
      SetStaticIpAddress('Network card name','192.168.1.1','255.255.255.0');
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;

Question: is that except only going to catch exceptions from CoInitialize(nil); or also from SetStaticIpAddress('Network card name','192.168.1.1','255.255.255.0');?

To put it another way, is it possible to have my cake and eat it by having a bested try finally within a try except?


[update] the answer to #2 seems to be yes. This code shows both dialog boxes ...

procedure TForm3.FormCreate(Sender: TObject);
  var x, zero : Integer;
begin
   zero := 0;
   try
      try
        x := 42 div zero;
      finally
         MessageDlg('Divide by zero finally', mtInformation, [mbOK], 0);
      end;

   Except
     on E: Exception do
     MessageDlg('Divide by zero exception handled', mtInformation, [mbOK], 0);
   end;
end;
Community
  • 1
  • 1
Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551
  • Why are you trying to handle these exceptions at all. Don't handle them. – David Heffernan Sep 26 '12 at 03:00
  • 2
    Some thoughts , 1. Try ...finally is used to ensure the release of the resources allocated if an exception occurs. 2.) There is not a general rule when use try ...except block, that totally depends of your code design 3. about my answer to your question, Yes the exception block will catch the exceptions caused by `CoInitialize` or the `SetStaticIpAddress` because this method doesn't have a exception handler. – RRUZ Sep 26 '12 at 03:07
  • 2
    To elaborate, you usually don't ever need to write `try/except`. Usually that means something failed, and no amount of *handling* can undo that failure. Exceptions are, well, exceptional. Let exceptions float up to the top level. Now, `try/finally` is used to protect resources. For example, you allocate memory and then need to make sure that it is subsequently deallocated, no matter what. That's `finally`. – David Heffernan Sep 26 '12 at 03:10
  • 1
    Continuing the idea that exceptions are exceptional. If you expect it, don't let it be an exception. If you can handle it on the spot, handle it on the spot. Only if you can't handle it, make it an exception. And then, of course, you don't handle it because you can't. If you are dividing by something that could be zero, check for zero before you attempt to divide. If you believe that the divisor cannot be zero, divide away. But don't handle exceptions. Sure, you sometimes need to handle them, but almost always not. – David Heffernan Sep 26 '12 at 03:12
  • @DavidHeffernan 2 @ +1 but I admit that I thogught your first comment was a joke :-/ I can understand your philosohpy of "If you expect it, don't let it be an exception", but I can't control the 3rd party code that I call, much of which *will* rasie exceptions. And I diagree with "no amount of handling can undo that failure", for instance I can have a temporary condition such as database or network connection failure and recover gracefuly. Some applications do not have the luxury of being able to stop running. But I do like your "finally is used to protect resources". – Mawg says reinstate Monica Sep 26 '12 at 03:20
  • @RRZUZ +1. Thanks. My updated code post shows what you expclained. I begin to understand now and I sort of like a belt & beraces appraoch. The `finally` ensures resources are freed both for success & failure whereas the `except` lets me log information or mayeb inform the user and do general failure peocessing. – Mawg says reinstate Monica Sep 26 '12 at 03:23
  • Now, what about my first question - which sort of things can throw exceptions and need a Try clause and which not? Or do you recommend a Try in every fucntion, around all code? If not, how do you decide? – Mawg says reinstate Monica Sep 26 '12 at 03:37
  • 1
    @DavidHeffernan: There are cases where you have no choice but to catch the exception--anything where the circumstances can change between when you check and when you carry out the operation. The most common example of this is file handling. – Loren Pechtel Sep 26 '12 at 03:52
  • 1
    @David: Yet more dogma. You simply cannot make blanket statements such as "Do not handle exceptions". Some class libraries specifically use exceptions as their error reporting mechanism, and sometimes it's simply more efficient - and more logically correct (something you of all people should appreciate) - to *handle* exceptions rather than pre-emptively deal with the conditions that lead to them or let them "escape" up the stack. i.e. "I don't expect this, but I can handle it *if* it happens". – Deltics Sep 26 '12 at 04:58
  • @Deltics I said "Sure, you sometimes need to handle them, but almost always not." – David Heffernan Sep 26 '12 at 12:18
  • Sure, *eventually* you said that, after twice before expressing quite clearly the notion that exceptions shouldn't be handled. First absolutely and then retreating slightly and starting to couch things in terms of "usually", and even then you clung to the idea that the dogmatic approach is "almost always" the right one. I guess sometimes even the most dogmatic of people have to give up to reason when they simply can't avoid it, albeit reluctantly. ;) – Deltics Oct 03 '12 at 03:19

1 Answers1

5

While they both pertain to exception handling they are different beasts.

Try...Finally is for resource cleanup. It should always be used when you allocate resources that get cleaned up at the end of the routine. (Interpret "resources" broadly here--you need it for things like locks etc. also.)

Try...Except is for catching exceptions. Use it only when there is an exception that could happen that you have a reasonable way of handling. You should almost never simply grab all exceptions other than as part of a top-level error logging facility. (I won't say you should never catch all--for example, you're reading a config file and it's bad. Your only real choices are abort the program or squawk, use defaults and continue. In general users would probably prefer the latter.)

They can be nested to any depth (when you're allocating multiple resources you either must nest them or you must have some way of figuring out if a resource was obtained or not before letting go of it) and coexist freely.

Loren Pechtel
  • 8,945
  • 3
  • 33
  • 45
  • {+1 Yes, I am cominng round to that way of thinking. As I said to RRUZ above,"My updated code post shows what you expclained. I begin to understand now and I sort of like a belt & beraces appraoch. The finally ensures resources are freed both for success & failure whereas the except lets me log information or mayeb inform the user and do general failure peocessing. " – Mawg says reinstate Monica Sep 26 '12 at 03:35
  • Now, what about my first question - which sort of things can throw exceptions and need a Try clause and which not? Or do you recommend a Try in every fucntion, around all code? If not, how do you decide? – Mawg says reinstate Monica Sep 26 '12 at 03:37
  • 1
    @Mawg: It's not about what can throw exceptions, but about what you can recover from. – Loren Pechtel Sep 26 '12 at 03:53
  • +1 But, the point I wanted to make was - should I put Try blocks around *everything*? Do you? I guess it only mmakes sense to Try somethign that can raise an exception; what sort of thing is that? Or, to put it another way, is there anything that can't raise an exception? – Mawg says reinstate Monica Sep 26 '12 at 05:09
  • 3
    @Mawg: You have it backwards. You only put try...except blocks around things where you can reasonably handle the exception. If you can't plan out the specific exception and what you want to do about it you shouldn't be catching it other than for logging purposes anyway. If something went wrong that you weren't expecting you probably shouldn't continue to run the program--that's asking for data corruption. – Loren Pechtel Sep 26 '12 at 05:20
  • +1 I see your point. But it seems that you want the user to see fireworks rather than a polite little "something went wrong" box (ans logging would be useful). Also, if I have a "mission critical" application, I may be able accept that some sub-functions fail, so long as the core continues. E.G, my EKG machine should continue to run even if I can't save a file. – Mawg says reinstate Monica Sep 26 '12 at 07:00
  • 3
    If you decide to follow the suggestions from earlier commenters: (1) only use try/except in places where you can properly handle the exceptions and (2) use try/finally to clean up resources, then I suggest you look at Alister Christie nice movie about exceptions in constructors/destructors [http://codegearguru.com/video/030/TSuicide.html] and how you can handle them. He only uses try/finally blocks and leaves the handling of the exception to the application He explains the different options you have, and extends it to creating more than one object. – Jan Doggen Sep 26 '12 at 08:16
  • Good luck wrapping everying single routine in a try/except. Then when you've caught and handled the exception, what's next. The routine returns to the caller, but what's the caller going to do next? If the callee couldn't do it's job, presumably the caller is now stuck. It can't continue. Exceptions are not meant to be handled at the lowest possible location. They should be caught and handled at the point where the app knows what to do with them. If a message needs to be shown to the user, let the exception float right to the top, where the message can be shown. – David Heffernan Sep 26 '12 at 13:43
  • @Mawg: We aren't objecting to a top-level error handler that does a polite something-went-wrong, here's why I'm dying. As for your EKG machine--file IO errors are something you can anticipate and react to in a reasonable fashion. – Loren Pechtel Sep 26 '12 at 16:24