2016-09-30 5 views
-1

я пытался увидеть, если сигнал левши SIGSEGV может помочь справиться с необработанным исключением C++, я экспериментирую его:Почему обработчик сигналов для SIGSEGV не поймает мое исключение C++ throw?

#include <stdio.h> 
#include <execinfo.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <unistd.h> 
void handler(int sig) { 
    void *array[10]; 
    size_t size = backtrace(array, 10); 
    fprintf(stderr, "Error: signal %d:\n", sig); 
    backtrace_symbols_fd(array, size, STDERR_FILENO); 
    exit(1); 
} 
int main() 
{ 
    signal(SIGSEGV, handler); 
    throw 1; 
} 

$ г ++ -g h.cpp -rdynamic & & ./a.out

Terminate называется кинув экземпляр «межда» Прерванных (дампа ядра)

Ну, программа не печатает аварию стеки вызовов как я и ожидал. Мой вопрос:

До тех пор, пока он заканчивается, выполняет ли он какие-либо сигналы, такие как SIGSEGV? Есть ли системный вызов или posix api, который мог бы поймать даже исключения C++ и распечатывать стек вызовов?

Спасибо!

+0

броска дозы улова с 'уловом (...)' –

+0

Возможный дубликат [ C++ трассировка стека из необработанного исключения?] (http://stackoverflow.com/questions/3355683/c-stack-trace-from-unhandled-exception) + исключение не является нарушением сегментации (ошибка сегментации). – user1810087

+0

Почему вы ожидаете, что обработчик сигнала поймает это? – juanchopanza

ответ

2

Вы можете установить обработчик завершения с помощью std::set_terminate - тогда установленный обработчик будет вызван для необработанного исключения. Нет никакой надежной гарантии, но есть большая вероятность, что вызов abort, вызывающий вызов обработчика завершения, встречается в верхней части стека, который выбросил исключение, и поэтому вы все равно можете собрать обратную трассировку.

Кроме того, вы можете установить обработчик для SIGABRT, который будет работать так же:

#include <execinfo.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 

void handler(int sig, siginfo_t*, void*) { 
    void *array[10]; 
    size_t size = backtrace(array, 10); 
    fprintf(stderr, "Error: signal %d:\n", sig); 
    backtrace_symbols_fd(array, size, STDERR_FILENO); 
    exit(1); 
} 

void terminate_handler() 
{ 
} 

int main() 
{ 
    struct sigaction new_sigaction, old_sigaction; 
    new_sigaction.sa_flags = SA_SIGINFO; 
    new_sigaction.sa_sigaction = handler; 
    sigaction(SIGABRT, &new_sigaction, &old_sigaction); 
    throw 1; 
} 

Я лично предпочитаю обработчик завершения, так как в этом случае вы явно знаете причину. Если вызывается обработчик SIGABRT, вы должны понять, если это связано с тем, что необработанное исключение вызвало abort() или сигнал был отправлен другими способами.

0

От here

Если какая-либо функция, которая вызывается во время разматывания стеки, после инициализации объекта исключения и перед началом обработчика исключений, выходит с исключением, std::terminate называется.

Вкратце говорится, что исключение не было обнаружено. std::terminate называется. Это не так. от SEG. FAULT.

Ваша программа не вызывает исключения, поэтому вызывается std::terminate, но это не приводит к поведению sigfault.

-2

Я думаю, что вам нужно сделать

raise(SIGSEGV) 

, если вы хотите, чтобы в конечном итоге в обработчике:

#include <stdio.h> 
#include <execinfo.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <unistd.h> 
void handler(int sig) { 
    void *array[10]; 
    size_t size = backtrace(array, 10); 
    fprintf(stderr, "Error: signal %d:\n", sig); 
    backtrace_symbols_fd(array, size, STDERR_FILENO); 
    exit(1); 
} 
int main() 
{ 
    signal(SIGSEGV, handler); 
    raise(SIGSEGV); 
} 
+0

OP хочет поймать необработанное исключение C++. –

+0

Почему вы хотите обрабатывать исключение C++ с помощью C-функций? –

+0

Я не знаю ... Я только заметил, что он установил обработчик для SIGSEGV и предположил, что он хочет оказаться в этом обработчике. Следовательно, поднять SIGSEGV – Rik

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

  • Нет связанных вопросов^_^