Хорошо, так как он был запрошен:
Код примера C ++:
#include <typeinfo>
#include <exception>
extern "C" {
void sethandler(void (*func)(void)) { std::set_terminate(func); }
int throwingFunc(int arg) {
if (arg == 0)
throw std::bad_cast();
return (arg - 1);
}
}
Пример кода кода:
#include <stdio.h>
extern int throwingFunc(int arg);
extern void sethandler(void (*func)(void));
void myhandler(void)
{
printf("handler called - must've been some exception ?!\n");
}
int main(int argc, char **argv)
{
sethandler(myhandler);
printf("throwingFunc(1) == %d\n", throwingFunc(1));
printf("throwingFunc(-1) == %d\n", throwingFunc(-1));
printf("throwingFunc(0) == %d\n", throwingFunc(0));
return 0;
}
Когда я компилирую эти два, свяжите их вместе и запустите (Ubuntu 10.04, gcc 4.4.5, x64), я получаю:
$ ./xx throwingFunc(1) == 0 throwingFunc(-1) == -2 handler called - must've been some exception ?! Aborted
Так что, пока вы можете перехватывать исключения из C, это вряд ли достаточно, потому что поведение C ++ во время выполнения после std::terminate()
не определено, и потому, что обработчик не получает никакой информации о статусе (чтобы различать типы исключений и / или источники). Обработчик ничего не может очистить.
Кстати, я специально выбрал std::bad_cast()
как тип исключения в этом примере. Это связано с тем, что бросание, которое иллюстрирует разницу в поведении между std::set_unexpected()
и std::set_terminate()
- неожиданным обработчиком, будет вызвано для всех исключений non std::bad_*
, тогда как для того, чтобы поймать стандартные исключения, требуется обработчик завершения ... см. дилемма? Жгут проводов слишком широк для практического использования: (