{"id":421,"date":"2009-04-25T11:51:44","date_gmt":"2009-04-24T23:51:44","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=421"},"modified":"2009-08-07T14:58:07","modified_gmt":"2009-08-07T02:58:07","slug":"raising-the-dead","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/421\/","title":{"rendered":"Raising The Dead"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>What can possibly go wrong in the simple act of modifying the message of an exception to add some additional diagnostic information and then re-raising it?<\/p>\n<p>Quite a lot actually, and all from one simple mistake.<\/p>\n<p><!--more--><\/p>\n<p>Here&#8217;s a simplified version of a fairly common construct that you will encounter in Delphi code:<\/p>\n<pre class=\"delphi\">  var\r\n    a: Integer;\r\n  begin\r\n    try\r\n      a := 0;\r\n      Caption := IntToStr(100 div a);\r\n    except\r\n      on e: Exception do\r\n      begin\r\n        e.Message := 'Oops: ' + e.Message;\r\n        raise e;\r\n      end;\r\n    end;\r\n  end;<\/pre>\n<p>The intention is to add some additional diagnostic information to an exception message to assist in debugging (assuming it is not subsequently handled by some exception handler further up the stack), but without handling the exception itself.  i.e. to re-raise the exception.<\/p>\n<p>Fairly innocuous and entirely straightforward &#8211; most experienced Delphi developers can probably do this in their sleep.<\/p>\n<p>Which is I think what happened here &#8211; sleep-coding I mean &#8211; because if you compile and run this code your exception handling will cause an apparent meltdown in your application.  After the initial exception is reported &#8211; seemingly normally &#8211; you will then encounter access violations and even external exceptions.<\/p>\n<p>Some of you may have spotted the problem already, but it took me 20 minutes of trying to figure out why such seemingly simple and harmless code was causing access violations and external exceptions etc etc.<\/p>\n<p>How can raising an exception do that?  Perhaps the method was being invoked on an invalid instance or some other similar bad pointer was getting involved in the situation somehow (which was far more complex than this simplified version).<\/p>\n<p>The problem of course lay in the mostly harmless looking:<\/p>\n<pre class=\"delphi\">      raise e;<\/pre>\n<p>To re-raise an exception you do not specify an exception instance.  You only do that when raising a brand new exception.  By referencing the &#8220;caught&#8221; exception instance &#8220;e&#8221; in the raise statement, the runtime will naively handle that exception (destroying the exception instance) and then goes right ahead and raises that destroyed &#8211; dead &#8211; instance.<\/p>\n<p>The exception instance gets handled AND re-raised and when the already handled (destroyed) exception arrives at another exception handler, all hell breaks loose.<\/p>\n<p>It strikes me that the compiler\/RTL between them should be able to tell when you do this and treat &#8220;raise e&#8221; as simply &#8220;raise&#8221; when &#8220;e&#8221; is a reference to the currently-being handled exception.<\/p>\n<p>But for now, it&#8217;s something to be wary of.<\/p>\n<h2>Footnote<\/h2>\n<p>There&#8217;s an entirely clean triple-entendre in this post&#8217;s title.<\/p>\n<p>1. The technical aspect covered above &#8211; raising a handled (dead) exception<\/p>\n<p>2. Stress related health concerns that have been bothering me for the past 12 months or so and which came to a head at the end of last year, are hopefully if not behind me then at least waving as I sail them by on the freeway.\u00a0 I did not actually die &#8211; quite obviously &#8211; but believed I was close to it on more than one occasion.\u00a0 and which caused me to take a break from engaging in the Delphi community including this blog.\u00a0 My activity may not be as high as it once was, at least for a while, but I am re-raised at last.<\/p>\n<p>3. It is no exaggeration to say that a factor, albeit a small one, in my recovery has been the undoubted resurgence in the vitality of Delph itself.\u00a0 A raising from the dead (again? some might say) of Delphi.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> What can possibly go wrong in the simple act of modifying the message of an exception to add some additional diagnostic information and then re-raising it? Quite a lot actually, and all from one simple mistake.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[292,70,69],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-6N","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":3037,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/3037\/","url_meta":{"origin":421,"position":0},"title":"ReRaise Exception Bug in 10.4.1 x86 Compiler","date":"09 Dec 2020","format":false,"excerpt":"I just ran into a very frustrating issue in Delphi 10.4.1 with long-standing, basic functionality that is now broken in certain circumstances. Fortunately there is a work-around in those certain circumstances, but it's not pretty. The Problem: Re-Raising an exception causes an immediate Access Violation error at the raise statement\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/image.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2956,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2956\/","url_meta":{"origin":421,"position":1},"title":"Introducing: Smoketest 2.0","date":"24 Sep 2019","format":false,"excerpt":"Meet the new Smoketest. Nothing like the old Smoketest. A new, ultra-lightweight unit testing framework with xUnit 2.x result output (and the ability to support other output formats as needed).","rel":"","context":"In &quot;automation&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/vape_2.jpg?fit=1200%2C307&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":3045,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/3045\/","url_meta":{"origin":421,"position":2},"title":"Big Updates to Smoketest 2.x","date":"19 Dec 2020","format":false,"excerpt":"A little over a year ago, I released Smoketest 2.0, a complete re-write of the Smoketest unit testing framework first implemented some years ago. Other things then consumed my time, but in the past couple of months, Smoketest has rapidly progressed through no less than 4 (four!) fairly significant feature\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/vape_2.jpg?fit=1200%2C307&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1930,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1930\/","url_meta":{"origin":421,"position":3},"title":"VCL Threading &#8211; Indeterminate Lifetimes","date":"18 Oct 2013","format":false,"excerpt":"Sometimes when you launch a thread you don't know when it will complete whatever processing it is tasked with. Sometimes you do. Sometimes it may never complete and will require that you expressly terminate it. Usually any given thread will have a lifecycle that is at least consistently one or\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":194,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/194\/","url_meta":{"origin":421,"position":4},"title":"Another Week, Another Poll","date":"17 Aug 2008","format":false,"excerpt":"Last weeks poll asked which was your first Delphi version.\u00a0 It may or may not come as a surprise that the results essentially provided a list of Delphi versions largely sorted by age. The one exception was that (of visitors to this blog) more gained their first Delphi experience from\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2624,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2624\/","url_meta":{"origin":421,"position":5},"title":"Expressive If and Case &#8230;","date":"25 Apr 2017","format":false,"excerpt":"A quick post on a small but hugely useful little language feature in Oxygene... if expressions. Many people will be familiar with the so-called ternary operator. Delphi developers will also be aware that there is no direct equivalent in Delphi. In 'C' and other languages we can write a statement\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/421"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=421"}],"version-history":[{"count":5,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/421\/revisions"}],"predecessor-version":[{"id":477,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/421\/revisions\/477"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}