From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Alf P. Steinbach" Newsgroups: gmane.emacs.help Subject: Re: How to exit out of a function ? what is try-catch-throw in terms of Program Counter Date: Tue, 23 Oct 2007 21:53:23 +0200 Organization: Posted via Supernews, http://www.supernews.com Message-ID: <13hsk5u8tekg618@corp.supernews.com> References: <1192913158.922454.108100@k35g2000prh.googlegroups.com> <13hl1rug786p1f2@corp.supernews.com> <1193162818.247085.305430@q3g2000prf.googlegroups.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1193172119 26935 80.91.229.12 (23 Oct 2007 20:41:59 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 23 Oct 2007 20:41:59 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Tue Oct 23 22:42:00 2007 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1IkQZc-0008Sm-6k for geh-help-gnu-emacs@m.gmane.org; Tue, 23 Oct 2007 22:42:00 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IkQZU-0003Lg-1u for geh-help-gnu-emacs@m.gmane.org; Tue, 23 Oct 2007 16:41:52 -0400 Original-Path: shelby.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!tethys.csu.net!nntp.csufresno.edu!sn-xt-sjc-03!sn-xt-sjc-09!sn-post-sjc-01!supernews.com!corp.supernews.com!not-for-mail Original-Newsgroups: gnu.emacs.help,comp.lang.c,comp.lang.c++ User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20051201 Thunderbird/1.5 Mnenhy/0.7.3.0 In-Reply-To: <1193162818.247085.305430@q3g2000prf.googlegroups.com> Original-X-Complaints-To: abuse@supernews.com Original-Lines: 248 Original-Xref: shelby.stanford.edu gnu.emacs.help:153249 comp.lang.c:828375 comp.lang.c++:954504 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:48743 Archived-At: * gnuist006@gmail.com: > On Oct 20, 3:55 pm, "Alf P. Steinbach" wrote: >> The closest equivalent in C would be a 'longjmp'. However, a C++ >> exception is more limited, in that it will only jump up the call chain, >> and it's more powerful, in that it will destroy local objects as it does >> so. Also, if you use 'longjmp' in C++ you're practically doomed (unless >> you use it to jump between co-routines with their own stacks), because >> 'longjmp' doesn't destroy local objects. > > Sure you have good ideas. Note that some people could read that as an attempt at insulting. > I still would like an equivalent implementation explained. Ofcourse, > smart > companies and smart programmers were doing all this before C++ came > and even in LISP they have atleast two of try catch throw. Ada introduced to the wider community much that was subsequently adopted in C++. Interestingly, (much of) the STL was implemented in Ada before it was implemented in C++. And perhaps also interestingly, Ada's high level thread primitives are seemingly now /not/ considered for C++. Now as for equivalence, you don't really want C code, because that would have to emulate C++ objects! But in C++ such longjm-based code is hairy compiler-dependent stuff, with formally Undefined Behavior. Also, as an example of equivalent-except-for-efficiency, note that a call of a virtual function can be specified equivalently as a dynamic lookup in most derived class, base class, base class' base class and so on, a search up the base class chain, but is in actuality implemented as a table look-up (with all compilers). Exceptions are implemented in more than just one main way. However, analogously to the case with virtual functions, equivalent code that performs dynamic lookup, such as the code below, is extremely ineffecient compared to the Real Thing(TM). Depending on the actual implementation of exceptions, there can be no overhead at all for normal case code. #include #include #include #include #include #if defined( _MSC_VER ) # define LNGJMP_DESTROYS_AUTOMAGICALLY #elif defined( __GNUC__ ) # undef LNGJMP_DESTROYS_AUTOMAGICALLY # // No automatic destruction, at least in MingW 3.4.4 version. #else # error Your compiler is not supported by this program. #endif struct AbstractLngjmpCleanup { virtual ~AbstractLngjmpCleanup() {} virtual void destroy() = 0; }; template< typename T > struct LngjmpCleanup: AbstractLngjmpCleanup { T* myTarget; LngjmpCleanup( T& target ): myTarget( &target ) {} virtual void destroy() { #ifndef LNGJMP_DESTROYS_AUTOMAGICALLY myTarget->T::~T(); // Call destructor on target. #endif } }; struct LongjmpCleanups { std::vector myDestroyers; ~LongjmpCleanups() { for( size_t i = 0; i < myDestroyers.size(); ++i ) { delete myDestroyers.at( i ); } } template< typename T > void add( T& target ) { myDestroyers.push_back( new LngjmpCleanup( target ) ); } void destroyAll() { for( size_t i = 0; i < myDestroyers.size(); ++i ) { myDestroyers.at( i )->destroy(); } } }; template< typename T > void say( T const& v ) { std::cout << v << std::endl; } struct Whatever { std::string myId; Whatever( std::string id ): myId( id ) { say( "Constructed " + myId + "." ); } ~Whatever() { say( "Destroyed " + myId + "." ); } }; jmp_buf* pReturnAddress = 0; void bottom() { LongjmpCleanups destroyers; LngjmpCleanup destroyersDestroyer( destroyers ); Whatever localObject( "bottom()'s local object" ); destroyers.add( localObject ); say( "Executing body of bottom()." ); say( "Throwing simulated exception." ); { destroyers.destroyAll(); destroyersDestroyer.destroy(); longjmp( *pReturnAddress, 1 ); } } void middle() { jmp_buf returnAddress; jmp_buf* pOldReturnAddress; LongjmpCleanups destroyers; LngjmpCleanup destroyersDestroyer( destroyers ); Whatever localObject( "middle()'s local object" ); destroyers.add( localObject ); pOldReturnAddress = pReturnAddress; if( setjmp( returnAddress ) == 0 ) { pReturnAddress = &returnAddress; say( "Executing body of middle(), calling bottom()." ); bottom(); pReturnAddress = pOldReturnAddress; } else { destroyers.destroyAll(); destroyersDestroyer.destroy(); pReturnAddress = pOldReturnAddress; longjmp( *pReturnAddress, 1 ); } } void top() { jmp_buf returnAddress; jmp_buf* pOldReturnAddress; LongjmpCleanups destroyers; LngjmpCleanup destroyersDestroyer( destroyers ); Whatever localObject( "top()'s local object" ); destroyers.add( localObject ); pOldReturnAddress = pReturnAddress; if( setjmp( returnAddress ) == 0 ) { pReturnAddress = &returnAddress; say( "Executing body of top(), calling middle()." ); middle(); pReturnAddress = pOldReturnAddress; } else { destroyers.destroyAll(); destroyersDestroyer.destroy(); pReturnAddress = pOldReturnAddress; longjmp( *pReturnAddress, 1 ); } } int main() { jmp_buf returnAddress; pReturnAddress = &returnAddress; if( setjmp( returnAddress ) == 0 ) { say( "Main business code, calling top()..." ); top(); return EXIT_SUCCESS; } else { say( "Caught simulated exception!" ); return EXIT_FAILURE; } } Main business code, calling top()... Constructed top()'s local object. Executing body of top(), calling middle(). Constructed middle()'s local object. Executing body of middle(), calling bottom(). Constructed bottom()'s local object. Executing body of bottom(). Throwing simulated exception. Destroyed bottom()'s local object. Destroyed middle()'s local object. Destroyed top()'s local object. Caught simulated exception! Now I leave it as an exercise to reimplement this program to use C++ exceptions instead of longjmp, and perhaps compare clarity (and efficiency, if that's interesting). Cheers, & hth., - Alf -- A: Because it messes up the order in which people normally read text. Q: Why is it such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail?