Вопрос

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

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

Какие есть варианты сделать что-то похожее с GCC?

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

Почему бы не использовать стандартные исключения 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 ++ также имеет & # 8220; catchall & # 8221; предложение, так что если вы хотите регистрировать исключения, вы можете использовать следующую оболочку:

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

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

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

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

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

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

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

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

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

Перехват исключений C ++ с помощью catch (...) уже ставит вас в сумеречную зону.

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

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

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

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

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

Кроме того, вы можете иметь более 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 */
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top