tag:blogger.com,1999:blog-2428374771421713311.post8732856061697606879..comments2024-03-10T12:04:17.661-07:00Comments on The Oracle at Delphi: try...finally.Anonymoushttp://www.blogger.com/profile/10119008505905401707noreply@blogger.comBlogger32125tag:blogger.com,1999:blog-2428374771421713311.post-25704185610985936332006-11-03T22:50:37.000-08:002006-11-03T22:50:37.000-08:00I figured the anwer to my question would be nested...I figured the anwer to my question would be nested try..finallys but do you actually do this for small objects? What if you were creating 5 objects? This would make the code look "unnecessary" ugly, and as others have mentioned if you are getting exceptions creating small object like stringslists then leaking an instance of TStringList may not be your biggest problem. <br><br>I guess if I was creating 2 objects of TEatALotOfMemory I would do nested try..finallys or maybe put the creating of the objects in the beginning of the try..finally block but initialize the variables to nil before creating them.Fredrik Loftheimnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-88231837181581162342006-11-03T22:58:28.000-08:002006-11-03T22:58:28.000-08:00meant to say "that encourages" not "...meant to say "that encourages" not "they encourages"Mark Tiedenoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-635874754208096692006-11-04T10:22:30.000-08:002006-11-04T10:22:30.000-08:00Mark, That example is of a try..except clause and...Mark,<br><br><br> That example is of a try..except clause and was meant to demonstrate handling a specific type of exception. I agree it should have included a try..finally block, but I imagine that doing that would have distracted from what was being discussed.<br><br><br>Allen.Allen Bauerhttp://blogs.codegear.com/abauernoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-67906405129144649372006-11-04T16:50:34.000-08:002006-11-04T16:50:34.000-08:00To Alexey:The reason is SPEED. Sometimes superfluo...To Alexey:<br><br><br>The reason is SPEED. Sometimes superfluous initialization of local variables will slow down a program distinctly.Kryvichnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-9019820327400053632006-11-04T17:02:00.000-08:002006-11-04T17:02:00.000-08:00Allen,Thank you for interesting articles. I think ...Allen,<br><br><br>Thank you for interesting articles. I think they can be added to the Delphi help file.<br><br><br>Just look at PHP documentation: every one page has very useful "User contributed notes" which give additional information about subject.Kryvichnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-80149979806934744522006-11-06T04:23:27.000-08:002006-11-06T04:23:27.000-08:00My "favorite" bad example of exeption co...My "favorite" bad example of exeption code is when someone wries code that swallows any and all exceptions. It looks like this:<br><br><br>try<br><br> ...do something...<br><br>except<br><br>end;<br><br><br>This is usually done when they have some problem that they want to avoid bubbling up, but rather than handling the specific error or error type, they swallow any exception. This makes debuggin a nightmare, because it ends up masking the real source of the problem and you end up with very unpredictable results.David R. Robinsonnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-8367403895425642302006-11-03T02:50:57.000-08:002006-11-03T02:50:57.000-08:00I like the D approach to these problems. Those try...I like the D approach to these problems. Those try/finally blocks can get quite messy. D supports "scope guarding", which basically lets you set code to run "on scope exit". This way the code for creating and releasing a resource can be grouped together.<br><br><br>http://www.digitalmars.com/d/exception-safe.html<br><br>(search for "scope(exit)")<br><br><br>Maybe consider adding something similar to Delphi :)<br><br>Justin Crowellnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-30724298035511026202006-11-03T03:01:10.000-08:002006-11-03T03:01:10.000-08:00I often use the wrapper object method Roddy mentio...I often use the wrapper object method Roddy mentioned (aka RAII idiom) as well.Justin Crowellnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-86858575144293017092006-11-03T03:01:52.000-08:002006-11-03T03:01:52.000-08:00You can get scope based object management in Delph...You can get scope based object management in Delphi via the use interfaced objects. See this article for a primer:<br><br><br>http://www.thedelphimagazine.com/samples/1415/1415.htmSean Fishernoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-85091396091128203902006-11-03T07:17:48.000-08:002006-11-03T07:17:48.000-08:00Fredrik:I believe you would have to next them such...Fredrik:<br><br><br>I believe you would have to next them such as:<br><br><br>var<br><br> Obj1,Obj2: TMyClass;<br><br>begin<br><br> Obj1 := TMyClass.Create;<br><br><br> try<br><br> Obj2 := TMyClass.Create;<br><br><br> try<br><br> ...<br><br> finally<br><br> Obj2.Free;<br><br> end;<br><br> finally<br><br> Obj1.Free;<br><br> end;<br><br>end;Patricio Moschcovichnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-69422237426144631992006-11-03T07:18:27.000-08:002006-11-03T07:18:27.000-08:00Sorry typo: meant "nest" them, not "...Sorry typo: meant "nest" them, not "next" themPatricio Moschcovichnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-87967065547282555762006-11-03T07:55:50.000-08:002006-11-03T07:55:50.000-08:00Allan, your example makes it look like pointers ar...Allan, your example makes it look like pointers are not initialized to nil by Delphi, but rather that you have to do this yourself. I always write my code so it would not matter, but I once knew someone who told me that all references were initialized to nil by Delphi. They tended to use the <br><br><br>try<br><br> obj := something.create;<br><br> ...do stuff...<br><br>finally<br><br> obj.Free;<br><br>end;<br><br><br>construction that you mention.John Jacobsonnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-49485050917659263672006-11-03T08:17:46.000-08:002006-11-03T08:17:46.000-08:00Frederik, As Patricio pointed out, you should next...Frederik, <br><br><br>As Patricio pointed out, you should next the try..finally blocks. <br><br><br>John, <br><br>Normal pointer *local* variables are *not* initialized to 0 for you which is why you should move that code outside the try..finally block. For the "managed" types such as strings, dynamic arrays, variants and interfaces, they *are* initialized on entry to the function. <br><br><br>Allen.Allen Bauerhttp://blogs.codegear.com/abauernoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-50513319035043505992006-11-03T09:21:38.000-08:002006-11-03T09:21:38.000-08:00John,Globals *are* initialized to 0. Class member...John,<br><br><br>Globals *are* initialized to 0. Class members *are* initialized. Only local variables (ie. stack variables) are *not* initialized. Unmanaged record fields are *not* initialized unless that record is declared as a global.Allen Bauerhttp://blogs.codegear.com/abauernoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-79797474402560252272006-11-03T17:17:28.000-08:002006-11-03T17:17:28.000-08:00I agree with IDL that this kind of information sho...I agree with IDL that this kind of information should be included in Delphi documentation.Ahtonoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-75067658447721988802006-11-03T17:19:16.000-08:002006-11-03T17:19:16.000-08:00Just to add, the reason why you see so much "...Just to add, the reason why you see so much "bad" exception handling code is that probably it is not exaplained well enough in the documentation.Ahtonoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-15496121341337349222006-11-16T07:52:37.000-08:002006-11-16T07:52:37.000-08:00...oops meant this of course:finally Free; end;...oops meant this of course:<br><br>finally <br><br> Free; <br><br>end; <br><br>Craig Farrellnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-43316664030709554772006-12-18T06:02:44.000-08:002006-12-18T06:02:44.000-08:00Allen,That was a really great article. ThanksEddi...Allen,<br><br><br>That was a really great article. Thanks<br><br><br>Eddie<br><br>Eddie Meyernoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-3675965940955281822006-12-18T06:37:28.000-08:002006-12-18T06:37:28.000-08:00varObj1,Obj2: TMyClass;begin Obj1 := nil; Obj2 :...var<br><br>Obj1,Obj2: TMyClass;<br><br>begin<br><br> Obj1 := nil;<br><br> Obj2 := nil;<br><br> try<br><br> Obj1 := TMyClass.Create;<br><br> Obj2 := TMyClass.Create;<br><br> ....<br><br> finally<br><br> Obj1.Free;<br><br> Obj2.Free;<br><br> end;<br><br>end;<br><br><br>anything wrong with that?Will Bnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-29994977903167423462006-11-03T02:42:32.000-08:002006-11-03T02:42:32.000-08:00Worth mentioning that with C++ (and thus C++Builde...Worth mentioning that with C++ (and thus C++Builder), try..finally is very rarely needed or used. The automatic destruction of stack-based objects when they're out of scope means thatyou can have it handled automagically via auto_ptrs or similar.<br><br><br>I use the same approach with busy cursors, mutexes, and even BeginUpdate/Endupdate pairings.Roddy Prattnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-82904678438912672392006-11-03T03:42:22.000-08:002006-11-03T03:42:22.000-08:00The automatic destruction that C++ gives you is ni...The automatic destruction that C++ gives you is nice, sure. Also the various "tricks" of using an interfaced object are also somewhat "clever." The problem with many of those mechanism is that they're *not* ad-hoc and require you to go create a new class type or interface type when you need to manage some resource for which you don't already have something setup. C++'s auto_ptr is nice if you're doing memory block or object allocations. But what about file handles, synchronization objects, GDI handles, etc...? <br><br><br>That was part of the reason I specifically did *not* mention all of those. Sometimes breaking one's train of thought and take a detour to bang out some resource manager class or interface is not good. By using an inline try...finally block, the workflow is preserved and the resource management needs are addressed.<br><br><br>However, if you already have those other mechanisma at your disposal, then by all means take advantage of them... Although the interface "trick" is a little opaque and tends to "obfuscate" things too much.Allen Bauerhttp://blogs.codegear.com/abauernoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-50413262207265511672006-11-03T03:45:35.000-08:002006-11-03T03:45:35.000-08:00Allen,It's a shame that great blog articles li...Allen,<br><br><br>It's a shame that great blog articles like these will never been seen again especially by those who need it the most (new Delphi programmers). It's also sad to see that the TurboExplorer site has been underdeveloped for 2 months now. Whatever happened to "the site where you can find everything Turbo: product information, articles, code samples, games, competitions and more!..."? It served as nothing more than a half baked marketing gimmick. The site could have been used to provide the needed resources and materials for new programmers to learn how to program in Delphi. What good is it to release a free software dev't tool, with the intension to lure new developers, if the logistical support to help new developers learn the language is not there? It's like the Internet before Google arrived..all the documentation and sample codes are scattered all over the place and you have to scavenge for it. Compound that with the frustration you get with the BDS Help and you end up turning off new users.<br><br><br>IDL<br><br>Impatient Delphi Loyalistnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-82681360262369443222006-11-03T04:43:24.000-08:002006-11-03T04:43:24.000-08:00Allen wrote: "C++'s auto_ptr is nice if y...Allen wrote: "C++'s auto_ptr is nice if you're doing memory block or object allocations. But what about file handles, synchronization objects, GDI handles, etc...?"<br><br><br>Suitable classes for things like that are either available in the RTL, or are pretty trivial to write. And if your objects don't need to be heap-based, you also can avoid the auto_ptr thing. But I *do* appreciate having try..finally in C++Builder: I tend to use that in an 'ad-hoc' way if I'm in a real hurry, and later refactor the code to use RAII classes.Roddy Prattnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-25940306210006558082006-11-03T05:23:46.000-08:002006-11-03T05:23:46.000-08:00How about this code below. If Obj1 is created succ...How about this code below. If Obj1 is created successfully but something goes wrong when creating Obj2, then the try...finally block will never get entered and Obj1 won't get freed!<br><br>How would you do this? I must admit have a lot of code that look like this.<br><br><br>var<br><br> Obj1,Obj2: TMyClass;<br><br>begin<br><br> Obj1 := TMyClass.Create;<br><br> Obj2 := TMyClass.Create;<br><br> try<br><br> ...<br><br> finally<br><br> Obj1.Free;<br><br> Obj2.Free;<br><br> end;<br><br>end;<br><br>Fredrik Loftheimnoreply@blogger.comtag:blogger.com,1999:blog-2428374771421713311.post-25912571863905607692006-11-03T08:57:17.000-08:002006-11-03T08:57:17.000-08:00<<Normal pointer *local* variables are *not*...<<Normal pointer *local* variables are *not* initialized to 0 for you which is why you should move that code outside the try..finally block. For the "managed" types such as strings, dynamic arrays, variants and interfaces, they *are* initialized on entry to the function.>><br><br><br>What about global pointers/references? What about members of a class? Are they initialized to nil?<br><br><br>I've always assumed that Delphi did not initialize any pointers/references to nil, but in the past I've known some programmers who claimed otherwise. Were they right, or was I?John Jacobsonnoreply@blogger.com