Имеет ли смысл ловить исключения в main (...)?

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

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);
}

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

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


EDIT: я согласен, что хорошо печатать ошибку исключения. Однако не лучше ли пересмотреть это исключение ? У меня такое чувство, что мы глотаем. это здесь...

7 ответов


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

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

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

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


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

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


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

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

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


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

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

Если исключение не поймано на любом уровне и будет избегать 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.


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


посмотрите на Библию C++, т. е. Stroustrup, у него есть пример, который также повторяется в прикладном программировании на C++. Рассуждения:

int main(void)
{
     try
     {
          // your code 
     }
     catch ( /* YourPossibleExceptions i.e. barfs you expect may occur */ )
     {
     }
     catch ( ... ) // unexpected errors, so you can exit gracefully
     {
     }
}

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