Имеет ли смысл отлавливать исключения в главном (…)?

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

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

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

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


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

15.12.2008 12:14:34
Как это можно проглотить? Код печатает сообщение об исключении и затем завершается. Что еще ты можешь сделать? Если вы отменили исключение, кто бы это увидел? Где это будет поймано? В конце концов, это точка входа в программу.
jalf 15.12.2008 17:00:59
7 ОТВЕТОВ
РЕШЕНИЕ

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

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

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

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

16
15.12.2008 12:57:27

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

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

6
15.12.2008 12:17:43
Вы правы, я ошибочно думал, что исключение будет напечатано. Это не тот случай.
Barth 15.12.2008 12:24:14

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

3
15.12.2008 12:20:19
Это только хорошая идея, пока в первый раз вам не придется отлаживать какое-то загадочное исключение, выброшенное из ада, знает где ... :)
Paulius 15.12.2008 12:34:25
тогда мы не можем напечатать это и отбросить это?
Barth 15.12.2008 12:42:19
Я думаю, что мы можем, но когда я отлаживаю - я редко смотрю на то, что напечатано - я обычно смотрю на значения в окне просмотра (если мне нужно).
Paulius 15.12.2008 13:14:53

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

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

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

6
15.12.2008 12:22:48

Взгляните на библию 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
     {
     }
}
0
1.11.2011 20:27:27
Да. Но, как я уже упоминал в своем ответе, это не очень помогает отладчику. Если исключение не перехвачено - отладчик покажет вам точное местоположение в источнике, где выбрасывается исключение. Таким образом, это имеет смысл только в сборках релиза.
Paulius 15.12.2008 12:33:17

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

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

Если исключение не перехватывается на каком-либо уровне и будет экранировано от 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.

5
23.05.2017 12:19:31

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

0
3.10.2012 08:30:26
Не могли бы вы ссылаться на спецификацию Windows, где говорится это? это обеспечит некоторый дополнительный контекст / авторитет для вашего ответа.
Josh Darnell 6.08.2012 13:57:40