2008-09-02 7 views
5

Я работаю над переносом приложения Visual C++ в GCC (должен строиться на MingW и Linux).Перенос исключительных ошибок в C++

Существующий код использует __try { ... } __except(1) { ... } блоки в нескольких местах, так что почти ничего (возможно, из-за ошибок типа памяти?) Приведет к выходу программы без минимального ведения журнала.

Каковы варианты выполнения чего-то подобного с GCC?

Редактировать: Спасибо за указатель на опции/EH в Visual Studio, теперь мне нужны некоторые примеры того, как обрабатывать сигналы в Linux. Я нашел this message с 2002 года.

Какие еще сигналы, кроме SIGFPE и SIGSEVG Следует ли мне следить? (В основном заботиться о тех, которые могут быть подняты из меня делать что-то неправильно)

Bounty Информация: Я хочу, чтобы мое приложение, чтобы иметь возможность самостоятельно войти как много условий ошибок, как это возможно, прежде чем он выйдет.

Какие сигналы я могу получить, и как правило, невозможно зарегистрировать сообщение об ошибке после? (Недостаточно памяти, что еще?)

Как я могу обрабатывать исключения и (что наиболее важно) сигналы портативным способом, что код, по крайней мере, работает одинаково в Linux и MingW. #ifdef в порядке.

Причина, по которой я не просто оберточный процесс, который регистрирует сбой, заключается в том, что по соображениям производительности я сохраняю запись данных на диск до последней минуты, поэтому, если что-то пойдет не так, я хочу сделать все возможные попытки написать данные перед выходом.

ответ

10

try {xxx} catch (...) {xxx} будет более переносимым, но может не поймать столько. Это зависит от настроек и условий компилятора.

Используя настройки VC++ по умолчанию, асинхронные (SEH) ошибки не доставляются в инфраструктуру C++ EH; Чтобы поймать их, вам нужно использовать обработчики SEH (__try/__ except). VC++ позволяет маршрутизировать ошибки SEH с помощью обработки ошибок C++, что позволяет catch (...) блокировать ошибки SEH; это включает ошибки памяти, такие как нулевые указатели. Details.

В Linux, однако, многие ошибки, которые Windows использует для SEH, обозначаются через сигналы. Они никогда не пойманы try/catch; для их обработки вам нужен обработчик сигнала.

0

Почему бы не использовать стандартные исключения C++ вместо собственного расширения MSFT? C++ имеет концепцию обработки исключений.

struct my_exception_type : public logic_error { 
    my_exception_type(char const* msg) : logic_error(msg) { } 
}; 

try { 
    throw my_exception_type("An error occurred"); 
} catch (my_exception_type& ex) { 
    cerr << ex.what << endl; 
} 

C++ также есть «прием все» положение, так что если вы хотите, чтобы войти исключения вы можете использовать следующую обертку:

try { 
    // … 
} 
catch (...) { 
} 

Однако, это не очень эффективно в C++, потому что создание такого общего wrapper означает, что код обработки должен быть вставлен в каждый последующий стек кадра компилятором (в отличие от управляемых систем, таких как .NET, где обработка исключений идет без дополнительных затрат до тех пор, пока не исключено какое-либо исключение).

+0

OP ищет что-то для решения исключительных условий более низкого уровня, чем исключения на языке языка C++. В мире POSIX это означает установку обработчиков сигналов (для большинства) всего. В MSVC механизм __try/__ catch выполняет аналогичные ошибки (включая эквивалент Win32 SEGFAULT) – 2008-11-07 02:07:17

0

Для портативности нужно попробовать использовать блоки try-catch для большинства ванильных исключений, а затем установить обработчик завершения (set_terminate_handler), чтобы иметь минимальный крючок, доступный для катастрофических условий выхода. Вы также можете попробовать добавить что-то вроде обработчика atexit или on_exit. Разумеется, ваша среда исполнения может быть причудливой или коррумпированной, когда вы вводите эти функции, поэтому будьте осторожны, насколько вы предполагаете разумную среду.

Наконец, при использовании регулярных пар примерочного улова вы можете рассмотреть возможность использования функции попробовать блоки, в отличие от открытия TRY блока в теле функции:

int foo(int x) try { 
    // body of foo 
} catch (...) { 
    // be careful what's done here! 
} 

они относительно неизвестный куском C++ и в некоторых случаях может потребовать восстановления даже в случае частичного (мелкомасштабного) повреждения стека.

Наконец, да, вы, вероятно, захотите изучить, какие сигналы вы можете продолжать самостоятельно или на которых вы можете прервать, и если вы хотите, чтобы на вашем месте было меньше механизмов обработки, вы можете подумать о том, нового оператора и компиляции, чтобы не генерировать исключения с плавающей запятой, если это необходимо (вы всегда можете проверить isnan (.), isfinite (.), на результатах FP, чтобы защитить себя).

В этой последней заметке будьте осторожны: я заметил, что функции классификации результатов с плавающей запятой могут находиться в разных заголовках под linux и windows ... поэтому вам может потребоваться их условное включение.

Если вы чувствуете себя куки, напишите все, используя setjmp и longjmp (это шутка ...).

-1

Один из способов, который прост в использовании, переносится и практически не использует любые ресурсы, - это поймать пустые классы. Я знаю, что сначала это может показаться странным, но это может быть очень полезно.

Вот пример, который я сделал для другого вопроса, который претендует на ваш вопрос тоже: link

Кроме того, вы можете иметь более чем на 1 улов:

try 
{ 
    /* code that may throw exceptions */ 
} 
catch (Error1 e1) 
{ 
    /* code if Error1 is thrown */ 
} 
catch (Error2 e2) 
{ 
    /* code if Error2 is thrown */ 
} 
catch (...) 
{ 
    /* any exception that was not expected will be caught here */ 
} 
0

Обработка исключений C++ с catch(...) уже ставит вас в сумеречной зоне.

Попытка поймать ошибки, не обнаруженные catch(...), ставит вас прямо в неопределенное поведение. Никакой код на C++ не будет работать. Ваш минимальный код регистрации может привести к запуску ракеты.

Моя рекомендация - даже не пытаться до catch(...). Исключайте только исключения, которые вы можете осмысленно и безопасно регистрировать и позволять ОС обрабатывать остальные, если они есть.

Отказоустойчивая отладка становится уродливой, если у вас есть ошибки обработки ошибок кода в верхней части основной причины.