Hi Marc, Marc> I have the following problem (not really a problem, but I'd like to Marc> understand, what's going on). Compiling the program as follows on AIX Marc> 4.3 with xlC_r, I get a very different result than on Linux with egcs: >From a semantic perspective, your results aren't different at all. As a matter of fact, your results are semantically identical, at least according to the C++ standard. However, your interpretation of the results being "different" is completely understandable. What you are seeing is just two different implementations of the C++ standard from two different vendors who have two different interpretations of how to handle what are commonly known as "automatically generated temporaries". To see the source of the confusion, it is necessary to trace through the path of execution. I've numbered the lines from your example below in order to refer to them. 1. class Except 2. { 3. public: 4. Except() { cout << "Except constructor\n"; } 5. Except(const Except &e) { cout << "Except copy constructor\n"; } 6. ~Except() { cout << "Except destructor\n"; } 7. void fun() { cout << "Except fun\n"; } 8. }; 9. 10. int main() 11. { 12. try 13. { 14. throw Except(); 15. } 16. 17. catch( Except x ) 18. { 19. cout << "Caught exception Except" << endl; 20. x.fun(); 21. } 22. catch(...) 23. { 24. cout << "Caught undefined exception " << endl; 25. } 26. 27. return 0; 28. } Sequence of events under Linux: 1) Construct an unnamed temporary Except object in the scope of the "try block" at line 14. This object is local to the "try block", and lives in its stack frame. 2) From this unnamed temporary, "copy construct" another Except object (again at line 14), which is the actual object which is "thrown". 3) Destroy the first unnamed temporary Except object as we leave the "try block" at line 15 (just like all local variables are destroyed as their stack frame is exited). 4) Copy construct the Except object named "x" in the first catch block at line 17. FYI, there is hardly ever a reason to catch an exception by value. Catch exceptions by reference as a matter of course. 5) Invoke the "fun" method on "x" at line 20. 6) Destroy "x" as we leave the "catch block" at line 21. 7) Destroy the originally thrown Except object (the one used to initialize "x") at line 21. Note that I am just "guessing" as to the order of events 6) and 7). The actual order of when the destructors are run may be reversed. To gain further insight into the lifetimes of objects (and automatically generated temporaries in particular) it is instructive to add an "Object ID number" to your objects that are printed in the constructors and destructors. I have done this to your Except class and attached it to this e-mail. I have added a column (the third column) to your table below to show what happens when I changed your example by catching the exception by reference instead of by value (which, as a general rule, is the proper way to catch exceptions). Note that I've used the "instrumented" version of your Except class so that the sequence of when objects are constructed and destructed is clearer. My results for the third column are from using egcs 1.1.2 under Linux (i.e. the stock compiler under RedHat Linux 6.0 Intel). I've also "lined up" the events so that they correspond to one another correctly. On AIX, the result is On Linux I get Linux (as I would expect it): (what I don't understand): (catch by reference) ----------------------- ---------------------------------- ---------------------------------- Except constructor Except constructor: object #1 Except constructor: object #1 Except copy constructor Except copy constructor: object #2 Except copy constructor: object #2 Except destructor: object #1 Except destructor: object #1 Except copy constructor: object #3 Caught exception Except Caught exception Except Caught exception Except Except fun Except fun: object #3 Except fun: object #2 Except destructor Except destructor: object #3 Except destructor: object #2 Except destructor Except destructor: object #2 -- Matthew D. Langston SLD, Stanford Linear Accelerator Center langston@SLAC.Stanford.EDU #include <iostream> class Except { public: Except() : objectID( ++counter ) { cout << "Except constructor: object #" << objectID << endl; } Except( const Except& e ) : objectID( ++counter ) { cout << "Except copy constructor: object #" << objectID << endl; } ~Except() { cout << "Except destructor: object #" << objectID << endl; } void fun() { cout << "Except fun: object #" << objectID << endl; } private: static int counter; int objectID; }; int Except::counter = 0; int main() { try { throw Except(); } catch( Except& x ) { cout << "Caught exception Except" << endl; x.fun(); } catch(...) { cout << "Caught undefined exception " << endl; } return 0; }
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:40 MET