Разматывание стека

Когда в некоторой области действия исключение выброшено, но не перехвачено, стек функциональных вызовов начинает разматываться и делается попытка перехватить исключение в следующем, внешнем блоке try...catch.

Разматывание стека вызовов означает, что функция, в которой исключение не

перехвачено, завершается, все ее локальные переменные уничтожаются

и управление возвращается оператору, ранее вызвавшему эту функцию. Если

этот оператор охвачен try-блоком, делается попытка перехватить исключение.

Если оператор не охвачен try-блоком, снова происходит разматывание стека.

Если никакой catch-обработчик так и не перехватывает исключение,

вызывается функция terminate для завершения программы. Программа на рис. 16.4

демонстрирует разматывание стека.

// Рис. 16.4: TEST4.cpp

// Демонстрация разматывания стека.

#include <iostream>

using std::cout;

using std::endl;

#include <stdexcept>

using std::runtime_error;

// function3 выбрасывает ошибку времени выполнения

void function3() throw (runtime_error)

{

cout << "In function 3" << endl;

// нет try-блока, стек разматывается, возврат в function2

throw runtime_error("runtime_error in function3");

} // конец function3

// function2 вызывает function3

void function2() throw (runtime_error)

{

cout << "function3 is called inside function2" << endl;

function3(); // стек разматывается, возврат в functionl

} // конец function2

// functionl вызывает function2

void functionl() throw (runtime_error)

{

cout << "function2 is called inside functionl" << endl;

function2(); // стек разматывается, возврат в main

} // конец functionl

// демонстрация разматывания стека

int main()

{

// вызвать functionl

try

{

cout << "functionl is called inside main" << endl;

functionl(); // вызвать functionl, выбрасывающую runtime_error Управление исключениями

} // конец try

catch (runtime_error &error) // обработать runtime_error

{

cout << "Exception occurred: " << error.what() << endl;

cout << "Exception handled in main" << endl;

} // конец catch

return 0;

} // конец main

/*

functionl is called inside main

function2 is called inside functionl

function3 is called inside function2

In function 3

Exception occurred: runtime_error in function3

Exception handled in main

*/

Блок try в main (строки 37-41) вызывает functionl (строки 27-31). Затем

functionl вызывает function2 (строки 20-24), которая в свою очередь

вызывает function3 (строки 11-17). Строка 16 функции function3 выбрасывает

объект runtime__error. Однако поскольку оператор throw в строке 16 не охвачен

никаким try-блоком, происходит разматывание стека: выполнение function3

завершается в строке 16, и управление возвращается оператору в function2,

который вызвал function3 (т.е. строке 23). Поскольку строка 23 не охвачена

никаким try-блоком, снова происходит разматывание стека — function2

завершается в строке 23 и возвращает управление оператору в functionl,

который вызвал function2 (т.е. строке 30). Строка 30 также не охвачена

try-блоком, и стек разматывается еще раз — functionl завершается в строке 30 и

возвращает управление оператору в main, вызвавшему functionl (т.е. строке 40).

Этот оператор охвачен try-блоком в строках 37-41, поэтому первый

подходящий catch-обработчик после этого try-блока (строки 42-46) перехватывает

и обрабатывает данное исключение. В строке 44 используется функция what,

чтобы вывести сообщение об ошибке. Как вы помните, это виртуальная

функция класса exception, которую можно переопределить в производном классе,

чтобы выводилось соответствующее сообщение.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: