2012-10-30 3 views
1

Я хотел получить информацию о stack unwinding и наткнулся на this page, что демонстрирует его в следующем примере. Как этот кусок cpp-кода сбрасывает?

#include <iostream> 
using namespace std; 

struct E { 
    const char* message; 
    E(const char* arg) : message(arg) { } 
}; 

void my_terminate() { 
    cout << "Call to my_terminate" << endl; 
}; 

struct A { 
    A() { cout << "In constructor of A" << endl; } 
    ~A() { 
    cout << "In destructor of A" << endl; 
    throw E("Exception thrown in ~A()"); 
    } 
}; 

struct B { 
    B() { cout << "In constructor of B" << endl; } 
    ~B() { cout << "In destructor of B" << endl; } 
}; 

int main() { 
    set_terminate(my_terminate); 

    try { 
    cout << "In try block" << endl; 
    A a; 
    B b; 
    throw("Exception thrown in try block of main()"); 
    } 
    catch (const char* e) { 
    cout << "Exception: " << e << endl; 
    } 
    catch (...) { 
    cout << "Some exception caught in main()" << endl; 
    } 

    cout << "Resume execution of main()" << endl; 
} 

Однако он получил ядро ​​сбрасывали, когда я собирал с г ++ /*clang++*.The выход заключается в следующем:

In try block 
In constructor of A 
In constructor of B 
In destructor of B 
In destructor of A 
Call to my_terminate 
已放弃 (核心已转储) #core dump 

Может кто-нибудь дать мне несколько советов?

+2

Ну, ваш 'terminate' ... не закончил программу! – avakar

ответ

2

Ответ заключается в том, что вы бросаете исключение, когда вы бросаете исключение.

В main() вы создаете экземпляр A. Затем вы выбрасываете исключение. До выловлено, A::~A называется, который также выдает исключение. Имея два исключения в полете в то же самое время, вызывает terminate() (или пользовательский эквивалент), который должен быть вызван (который по умолчанию вызывает прерывание(), которое отбрасывает ядро. В любом случае программа не может восстановить.)

Кроме того: это то, что приводит к правилу общей практики, где вы не должны бросать исключения в деструкторы, если только вы не хотите, чтобы он убивал вашу программу.

+0

* вызывает завершение вызова (которое по умолчанию вызывает прерывание(), которое удаляет ядро ​​*, вы не видели код правильно .OP имеет обработчик завершения на месте. –

+0

@Als Да, я сделал. Я обновил свой комментарий, чтобы отразить это, но это совсем не относится к делу. –

+0

@KazDragon Вы имеете в виду, что программа не может восстановить, даже если с указанным 'my_terminate()' –

0

set_terminate() ожидает, что функция предоставит ему terminate программа.

Функция, которая не принимает никаких параметров и возвращает пустоту. Функция должна не возвращается и должна завершить программа. terminate_handler - это тип указателя функции без параметров и возвращающего пустоты.

set_terminate автоматически вызывает прерывание() после вызова функции завершения, если вы не выходите из предоставленной функции. Просто добавьте exit(0); в my_terminate(), чтобы избежать этого прерывания().

+0

Итак, как я могу исправить этот сегмент правильно? –

+0

В стандарте C++ (18.6.3.3) ** нет ** мандата 'terminate()' для завершения программы. –

+0

@ Als Вы читали, почему я цитирую? Из [здесь] (http://www.cplusplus.com/reference/std/exception/set_terminate/) – tomahh

Смежные вопросы