www.gibmonks.com

Main Page




Previous Page
Next Page

[Page 823]

16.8. Stack Unwinding

When an exception is thrown but not caught in a particular scope, the function call stack is unwound, and an attempt is made to catch the exception in the next outer TRy... catch block. Unwinding the function call stack means that the function in which the exception was not caught terminates, all local variables in that function are destroyed and control returns to the statement that originally invoked that function. If a TRy block encloses that statement, an attempt is made to catch the exception. If a try block does not enclose that statement, stack unwinding occurs again. If no catch handler ever catches this exception, function terminate is called to terminate the program. The program of Fig. 16.4 demonstrates stack unwinding.

Figure 16.4. Stack unwinding.
(This item is displayed on pages 823 - 824 in the print version)

 1  // Fig. 16.4: Fig16_04.cpp
 2  // Demonstrating stack unwinding.
 3  #include <iostream>
 4  using std::cout;
 5  using std::endl;
 6
 7  #include <stdexcept>
 8  using std::runtime_error;
 9
10  // function3 throws run-time error
11  void function3() throw ( runtime_error )
12  {
13     cout << "In function 3" << endl;
14
15     // no try block, stack unwinding occur, return control to function2
16     throw runtime_error( "runtime_error in function3" );
17  } // end function3
18
19  // function2 invokes function3
20  void function2() throw ( runtime_error )
21  {
22     cout << "function3 is called inside function2" << endl;
23     function3(); // stack unwinding occur, return control to function1
24  } // end function2
25
26  // function1 invokes function2
27  void function1() throw ( runtime_error )
28  {
29     cout << "function2 is called inside function1" << endl;
30     function2(); // stack unwinding occur, return control to main
31  } // end function1
32
33  // demonstrate stack unwinding
34  int main()
35  {
36     // invoke function1
37     try
38     {
39        cout << "function1 is called inside main" << endl;
40        function1(); // call function1 which throws runtime_error
41     } // end try
42     catch ( runtime_error &error ) // handle run-time error
43     {
44        cout << "Exception occurred: " << error.what() << endl;
45        cout << "Exception handled in main" << endl;
46     } // end catch
47
48     return 0;
49  } // end main

 function1 is called inside main
 function2 is called inside function1
 function3 is called inside function2
 In function 3
 Exception occurred: runtime_error in function3
 Exception handled in main


In main, the TRy block (lines 3741) calls function1 (lines 2731). Next, function1 calls function2 (lines 2024), which in turn calls function3 (lines 1117). Line 16 of function3 tHRows a runtime_error object. However, because no try block encloses the tHRow statement in line 16, stack unwinding occursfunction3 terminates at line 16, then returns control to the statement in function2 that invoked function3 (i.e., line 23). Because no try block encloses line 23, stack unwinding occurs againfunction2 terminates at line 23 and returns control to the statement in function1 that invoked function2 (i.e., line 30). Because no try block encloses line 30, stack unwinding occurs one more timefunction1 terminates at line 30 and returns control to the statement in main that invoked function1 (i.e., line 40). The try block of lines 3741 encloses this statement, so the first matching catch handler located after this try block (line 4246) catches and processes the exception. Line 44 uses function what to display the exception message. Recall that function what is a virtual function of class exception that can be overridden by a derived class to return an appropriate error message.


[Page 824]

Previous Page
Next Page