Форум программистов, компьютерный форум CyberForum.ru

mingw32, SEH, std::exception, setjmp/longjmp, signal - C++

Восстановить пароль Регистрация
 
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
22.02.2012, 11:01     mingw32, SEH, std::exception, setjmp/longjmp, signal #1
Начал разбираться с вопросом - как понял - есть несколько вариантов: (в порядке обнаружения мною)

1) LibSEH - работает.
http://www.programmingunlimited.net/...page=mingw-seh

2) <eh.h>, _set_se_translator - долго мучался с заголовками, а когда скомпилил - не смог слинковать.

3) <excpt.h> - видимо, недоделанная версия LibSEH - работает неадекватно (или я чего-то не понял).

4) И тут я вспомнил про сигналы и setjmp/longjmp, накидал себе такой код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class SignalExceptionGuard
{
public:
    static const int handled_signals [];
    SignalExceptionGuard ();
    virtual ~SignalExceptionGuard ();
    /*
     * Можно выбрасывать в качестве исключений объекты классов,
     * которые имеют конструкторы от int.
     */
    template <class ExceptionType>
    inline void Try (int sig_code) throw() {if(sig_code) throw ExceptionType(sig_code);}
    /*
     * Для использования в качестве параметра в setjmp.
     */
    inline operator int* () {return jb;}
    /*
     * Преобразовывает другие виды исключений в стандартные исключения С++.
     */
    static inline void Try (std::function<void()> fn) throw()
    {
        SignalExceptionGuard seg;
        seg.Try<Exception>(setjmp(seg));
        fn();
    }
    /*
     * Фактически - это указатель на вызов setjmp, в который вернётся управление
     * при вызове longjml с этим указателем в ккачестве параметра.
     */
    jmp_buf jb;
private:
    /*
     * Uncopyable, unassignable.
     */
    SignalExceptionGuard (const SignalExceptionGuard&);
    SignalExceptionGuard& operator= (const SignalExceptionGuard&);
    /*
     * Для каждого потока свой стек объектов SignalExceptionGuard и отдельный указатель на верхушку.
     */
    static __thread SignalExceptionGuard* curr;
    /*
     * Обработчик сигнала.
     */
    static void sig_handler (int sig_code);
    SignalExceptionGuard* prev;
};
 
const int SignalExceptionGuard::handled_signals [] = {
//  SIGINT
//  SIGILL
//  SIGTERM
//  SIGBREAK
//  SIGABRT
/* floating point exception, e.g. zero-division */
    SIGFPE,
/* segmentation fault */
    SIGSEGV
};
 
__thread SignalExceptionGuard* SignalExceptionGuard::curr = nullptr;
 
void SignalExceptionGuard::sig_handler (int sig_code)
{
    if (curr) longjmp(curr->jb, sig_code);
}
 
SignalExceptionGuard::SignalExceptionGuard () :
    jb({0}), prev(curr)
{
    if (!curr)
    {
        for (size_t i = 0; i < COUNT(handled_signals); i++)
            signal(handled_signals[i], sig_handler);
    }
    curr = this;
}
 
SignalExceptionGuard::~SignalExceptionGuard ()
{
    curr = prev;
}
Тоже вроде бы работает.



ИТОГО:
Ни один из этих способов не раскручивает плюсовый стек поравильно, т.е. не вызывает деструкторы.
Очевидно, что внутри своего кода надо делать по-человечески - проверять значения и кидать плюсовые исключения.
Первый и четвёртый позволяют адекватно продолжить выполнение если, например, в вызове из сторонней либы что-то сломалось. Тем более, если либо загружена вручную (как плагин).


Уважаемые специалисты, дополните, пожалуста, меня или поправте, если я не прав.

К тому-же очень интересует вопрос - при выкидывании всех ли виндовых структурных исключений вызываются обработчики сигналов, и когда ещё в винде вызываются обработчики сигналов?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
22.02.2012, 11:10     mingw32, SEH, std::exception, setjmp/longjmp, signal #2
Цитата Сообщение от cyberguz Посмотреть сообщение
Начал разбираться с вопросом
С каким вопросом то?
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
22.02.2012, 11:17  [ТС]     mingw32, SEH, std::exception, setjmp/longjmp, signal #3
Ой, ну что Вы. Понятно же с каким - каша в голове.
Плюсовые исключения, виндовые SE, всякие расширения языка (в плане обработки SE) в VC и их аналоги для mingw, а потом ещё оказалось, что и сигналы к этому отношение имеют...
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
22.02.2012, 11:22     mingw32, SEH, std::exception, setjmp/longjmp, signal #4
cyberguz, ну так они все для разных целей служат. Зачем их смешивать?
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
22.02.2012, 12:12  [ТС]     mingw32, SEH, std::exception, setjmp/longjmp, signal #5
Отвечу вопросом на вопрос - почему в плюсах не выкидываются стандартные исключения при делении на 0, segmentation fault, переполнении, и т.д.

Я думаю так:
Понятно, что при записи под логически неверный, но валилдный указатель, может что-то испортиться, и об этом никто не узнает, пока программа не доберётся до того места. Если это будет указатель в сегмент данных, или кучу - ещё ладно, попортятся данные. А если в сегмент стека - понятно, что можно всё сломать. А вот если указатель указывает на сегмент кода, или константные данные, или указатель невалидный (вообще вне адресного пространства процесса) то что мешает выкинуть обычное исключение?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
22.02.2012, 12:22     mingw32, SEH, std::exception, setjmp/longjmp, signal #6
cyberguz, Эмм.. Потому что это ошибка не относится к исполнению кода на С++. Его раньше ловит система и шлет сигнал программе. Не стоит пытаться делать такие обертки.
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
22.02.2012, 12:42  [ТС]     mingw32, SEH, std::exception, setjmp/longjmp, signal #7
Это, конечно, философский вопрос.

Меня больше интересует соответствие сигналов и струтктурных исключений...
Luke
37 / 37 / 1
Регистрация: 21.02.2012
Сообщений: 95
22.02.2012, 12:43     mingw32, SEH, std::exception, setjmp/longjmp, signal #8
cyberguz, DWORD WINAPI GetLastError(void) - вернет код ошибки системы. есть полная классификация кодов. Оборачивай как хочешь их.
Например
в зависимости от возвращенного кода ошибка делай throw (исключение на твой выбор). и лови уже исключения c++ а не ошибки системы
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
22.02.2012, 12:54  [ТС]     mingw32, SEH, std::exception, setjmp/longjmp, signal #9
Забыл сказать - интересный момент - inline функции с setjmp не встаиваются.

И ещё - вот так - не работает, catch не ловит исключение.
C++
1
2
template <class ExceptionType>
    void Try (int sig_code) throw() {if(sig_code) throw ExceptionType(sig_code);}
А так (без throw()) - работает:
C++
1
2
template <class ExceptionType>
    void Try (int sig_code) {if(sig_code) throw ExceptionType(sig_code);}
А это почему?

Добавлено через 3 минуты
Luke,
http://en.wikipedia.org/wiki/Structu...ption_Handling
http://wm-help.net/books-online/book...64-18.html#h24
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.02.2012, 15:33     mingw32, SEH, std::exception, setjmp/longjmp, signal
Еще ссылки по теме:

C++ Не получается перехватить исключение, унаследованное от std::exception
Ошибка при работе с std::exception* C++
Создание своего класса исключений, наследование std::exception C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Luke
37 / 37 / 1
Регистрация: 21.02.2012
Сообщений: 95
22.02.2012, 15:33     mingw32, SEH, std::exception, setjmp/longjmp, signal #10
Цитата Сообщение от cyberguz Посмотреть сообщение
void Try (int sig_code) throw()
говорит что эта функция НЕ генерирует исключений
исправь на throw(...)
Yandex
Объявления
22.02.2012, 15:33     mingw32, SEH, std::exception, setjmp/longjmp, signal
Ответ Создать тему
Опции темы

Текущее время: 21:50. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru