Имеет ли смысл отлавливать исключения в основном (...)? - PullRequest
11 голосов
/ 15 декабря 2008

Я нашел код в проекте, который выглядит так:

int main(int argc, char *argv[])
{
  // some stuff

 try {
  theApp.Run();
 } catch (std::exception& exc) {
  cerr << exc.what() << std::endl;
  exit(EXIT_FAILURE);
 }
 return (EXIT_SUCCESS);
}

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

Видите ли вы какие-либо веские причины ловить исключения здесь?


РЕДАКТИРОВАТЬ: Я согласен, что это хорошо, чтобы напечатать ошибку исключения. Однако не лучше ли было бы сбросить исключение? У меня такое чувство, что мы его здесь глотаем ...

Ответы [ 7 ]

16 голосов
/ 15 декабря 2008

Если исключение не учтено, то стандарт не определяет, будет ли стек разматываться. Таким образом, на некоторых платформах будут вызываться деструкторы, а на других программа будет остановлена ​​немедленно. Ловля на верхнем уровне гарантирует, что деструкторы всегда вызываются.

Так что, если вы не работаете под отладчиком, возможно, будет разумно отлавливать все: (...), а также std :: exception. Тогда код вашего приложения можно очистить с помощью RAII даже при фатальном исключении. Во многих таких случаях вам на самом деле не нужно убирать, так как ОС сделает это за вас. Но, например, вы можете предпочесть отключаться от удаленных сервисов везде, где это возможно, и могут существовать ресурсы, внешние по отношению к процессу, такие как именованные каналы / мьютексы, которые вы предпочитаете уничтожать, а не вытекать.

Повторное исключение в main кажется мне ограниченным, поскольку вы уже потеряли контекст, в котором оно было изначально выброшено. Я полагаю, что отлов неперехваченного исключения в отладчике является более шумным, чем просто запись ошибки в std :: cerr, поэтому повторное создание было бы разумным шагом, если есть вероятность пропустить запись.

Если вы хотите, чтобы отладчик перехватывал непредвиденные условия в режиме отладки, который в режиме выпуска вызывает исключение, которое в конечном итоге приводит к выходу, то есть другие способы сделать это, кроме как оставить исключение необработанным, чтобы отладчик его увидел. Например, вы можете использовать макрос assert. Конечно, это не помогает в непредвиденных и непредсказуемых условиях, таких как аппаратные исключения, если вы используете SEH в .NET.

6 голосов
/ 15 декабря 2008

Try-catch в основной функции скрывает исключение от отладчика. Я бы сказал, это не хорошо.

С другой стороны, от клиентов не ожидается отладчиков, поэтому ловить исключения приятно. Так что это хорошо.

Лично я перехватываю все исключения в основной функции при создании релизной сборки и не делаю этого при построении конфигурации отладки.

6 голосов
/ 15 декабря 2008

Почему вы говорите, что исключение будет напечатано? Это не типичное поведение среды выполнения C ++. В лучшем случае вы можете ожидать, что его тип будет напечатан.

Кроме того, эта программа оставляет состояние «сбой», тогда как исключение может вызвать состояние завершения через прерывание (т. Е. С сигналом, указанным в коде выхода).

5 голосов
/ 15 декабря 2008

Простой пример ситуации, когда стек не раскручивался:
Почему деструктор не вызывается по исключению?

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

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

В результате я всегда ловлю все исключения в main ().

int main()
{
    try
    {
    }
    catch(std::exception const& e)
    {  /* LOG */
       // optimally rethrow
    }
    catch(...) // Catch anything else.
    {  /* LOG */
       // optimally rethrow
    }
}

Чтобы помочь с обнаружением проблем во время отладки. Получите ваши исключения из std :: exception, а затем вставьте точку останова в конструкторе для std :: exception.

3 голосов
/ 15 декабря 2008

Это глобальный блок catch. Это обычно для отображения приятного и понятного пользователю сообщения («Внутренняя ошибка») вместо загадочной распечатки исключений. Это может быть неочевидно из конкретного блока кода, но в целом это хорошая идея.

0 голосов
/ 06 августа 2012

Согласно спецификации Windows, main не разрешено бросать. (практически это приводит к сообщению, которое спрашивает, хотите ли вы отправить отчет об ошибке в Microsoft)

0 голосов
/ 15 декабря 2008

Взгляните на библию C ++, то есть Страуструпа, у него есть пример, который также повторяется в прикладном программировании на C ++. Аргументация:

int main(void)
{
     try
     {
          // your code 
     }
     catch ( /* YourPossibleExceptions i.e. barfs you expect may occur */ )
     {
     }
     catch ( ... ) // unexpected errors, so you can exit gracefully
     {
     }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...