From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Joel Yliluoma Newsgroups: gmane.emacs.help Subject: Re: How to exit out of a function ? what is try-catch-throw in terms of Program Counter Supersedes: Date: 23 Oct 2007 09:04:24 GMT Organization: /etc/news/organization Message-ID: References: <1192913158.922454.108100@k35g2000prh.googlegroups.com> Reply-To: s , don't NNTP-Posting-Host: lo.gmane.org X-Trace: ger.gmane.org 1193135091 19549 80.91.229.12 (23 Oct 2007 10:24:51 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 23 Oct 2007 10:24:51 +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 12:24:51 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 1IkGw4-0001r8-RY for geh-help-gnu-emacs@m.gmane.org; Tue, 23 Oct 2007 12:24:33 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IkGvw-0005d6-MK for geh-help-gnu-emacs@m.gmane.org; Tue, 23 Oct 2007 06:24:24 -0400 Original-Path: shelby.stanford.edu!newsfeed.stanford.edu!goblin1!goblin.stu.neva.ru!uio.no!newsfeed1.fi.sn.net!fi.sn.net!newsfeed2.fi.sn.net!news.song.fi!not-for-mail Original-Newsgroups: gnu.emacs.help,comp.lang.c,comp.lang.c++ Original-Followup-To: comp.lang.c++ User-Agent: slrn/0.9.8.1pl1 (Debian) Original-Lines: 195 Original-NNTP-Posting-Host: bisqwit.iki.fi Original-X-Trace: 1193130264 news.song.fi 3492 194.29.198.4:38573 Original-X-Complaints-To: abuse@song.fi Original-Xref: shelby.stanford.edu gnu.emacs.help:153217 comp.lang.c:828299 comp.lang.c++:954441 X-Mailman-Approved-At: Tue, 23 Oct 2007 06:22:44 -0400 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:48709 Archived-At: On Sat, 20 Oct 2007 20:45:58 -0000, gnuist006@gmail.com wrote: > NOTE: I am really afraid of try-catch-throw. I have never been > able to understand it since it does not exist in C and I cant > really visualize the construct in terms of C. How try-catch-throw is actually implemented depends on the compiler, but one can explain it like this. Assume the following C++ code is written: #include // here's a sample object with a constructor and destructor // to demonstrate scope. class someobj { public: someobj() { std::puts("constructor"); } ~someobj() { std::puts("destructor"); } private: int x; // a dummy member variable }; // A dummy type, it could be a typedef of int or whatever. // Just for the purpose of throwing an exception of this particular type. struct someexceptiontype { }; void code_that_may_throw() { someobj obj; // instantiating someobj in this scope. if(false != true) { // some error situation happened, throw an exception. // someexceptiontype() instantiates an object of // "someexceptiontype" (without binding it into a variable), // and throw throws it. throw someexceptiontype(); } std::puts("wow, false is true"); } void some_intermediate_function() { std::puts("1"); code_that_may_throw(); std::puts("2"); } int main() { try { some_intermediate_function(); std::puts("executed without hitch"); } catch(int e) { std::puts("caught an int"); } catch(someexceptiontype e) { std::puts("caught someexceptiontype"); } std::puts("end of main()"); return 0; } The code above contains high-level concepts that approximately translate to the following lower-level concepts in C. It could be implemented differently, but the function is the same. #include typedef struct someobj { int x; } someobj; void someobj__construct(someobj* this) { puts("constructor"); if(__system_exception_ptr) goto __scope_end; __scope_end: ; } void someobj__destruct(someobj* this) { puts("destructor"); if(__system_exception_ptr) goto __scope_end; __scope_end: ; } struct someexceptiontype { }; /*** This global code is defined in some system library by the compiler */ void* __system_exception_ptr = (void*)0; int __system_exception_type = 0; void __clear_exception() { __system_exception_type = 0; free(__system_exception_ptr); __system_exception_ptr = (void*)0; } /*** End of compiler library code */ void code_that_may_throw(void) { someobj obj; // instantiating someobj in this scope. someobj__construct(&obj); if(__system_exception_ptr) goto __scope_end_before_obj; if(0 != 1) { someexceptiontype* e = (someexceptiontype*) malloc(sizeof(*e)); __system_exception_ptr = e; __system_exception_type = 2; /* ^ a compiler-specific tag that identifies the exception type */ goto __scope_end; } puts("wow, false is true"); if(__system_exception_ptr) goto __scope_end; __scope_end: ; someobj__destruct(&obj); __scope_end_before_obj: ; } void some_intermediate_function(void) { puts("1"); if(__system_exception_ptr) goto __scope_end; code_that_may_throw(); if(__system_exception_ptr) goto __scope_end; puts("2"); if(__system_exception_ptr) goto __scope_end; __scope_end: ; } int main(void) { some_intermediate_function(); if(__system_exception_ptr) goto try_catch; puts("executed without hitch"); if(__system_exception_ptr) goto try_catch; goto past_catch; try_catch: ; switch(__system_exception_type) { case 1: /* example denoting int type */ { __clear_exception(); puts("caught an int"); if(__system_exception_ptr) goto __scope_end; break; } case 2: /* example denoting someexceptiontype */ { __clear_exception(); puts("caught someexceptiontype"); if(__system_exception_ptr) goto __scope_end; break; } default: goto __scope_end; /* still not caught */ } past_catch: ; puts("end of main()"); if(__system_exception_ptr) goto __scope_end; __scope_end: ; return 0; } Of course, for efficiency reasons there is no "if" test after every function return for exceptions (rather, execution may be transferred to a dedicated stack and scope unfolder when an exception happens), but this was the easiest way to explain what happens as regards for scopes and execution paths. Also, in the exception handler (catch {}), the exception object is not supposed to be deallocated until the end of the handler, but for simplicity I wrote the deallocation first. Followups set to comp.lang.c++ . -- Joel Yliluoma - http://bisqwit.iki.fi/ : comprehension = 1 / (2 ^ precision)