17.4 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 trycatch block. Unwinding the function call stack means that the function in which the exception was not caught terminates, all local variables that have completed initialization 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, the program terminates. The program of Fig. 17.4 demonstrates stack unwinding.

Fig. 17.4 Demonstrating stack unwinding.

Alternate View

 1   // Fig. 17.4: fig17_04.cpp
 2   // Demonstrating stack unwinding.
 3   #include <iostream>
 4   #include <stdexcept>
 5   using namespace std;
 6
 7   // function3 throws runtime error
 8   void function3() {
 9      cout << "In function 3" << endl;
10
11      // no try block, stack unwinding occurs, return control to function2
12      throw runtime_error{"runtime_error in function3"}; // no print
13   }
14
15   // function2 invokes function3
16   void function2() {
17      cout << "function3 is called inside function2" << endl;
18      function3(); // stack unwinding occurs, return control to function1
19    }
20
21   // function1 invokes function2
22   void function1() {
23      cout << "function2 is called inside function1" << endl;
24      function2(); // stack unwinding occurs, return control to main
25    }
26   
27   // demonstrate stack unwinding
28   int main() {
29      // invoke function1
30      try {
31      cout << "function1 is called inside main" << endl;
32      function1(); // call function1 which throws runtime_error
33    }
34    catch (const runtime_error& error) { // handle runtime error
35       cout << "Exception occurred: " << error.what() << endl;
36       cout << "Exception handled in main" << endl;
37    }
38   }

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 30–33) calls function1 (lines 22–25). Next, function1 calls function2 (lines 16–19), which in turn calls function3 (lines 8–13). Line 12 of function3 throws a runtime_error object. However, because no try block encloses the throw statement in line 12, stack unwinding occurs—function3 terminates at line 12, then returns control to the statement in function2 that invoked function3 (i.e., line 18). Because no try block encloses line 18, stack unwinding occurs again—function2 terminates at line 18 and returns control to the statement in function1 that invoked function2 (i.e., line 24). Because no try block encloses line 24, stack unwinding occurs one more time—function1 terminates at line 24 and returns control to the statement in main that invoked function1 (i.e., line 32). The try block of lines 30–33 encloses this statement, so the first matching catch handler located after this try block (line 34–37) catches and processes the exception. Line 35 uses function what to display the exception message.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset