использование выгоды (…) (замещающий знак) для посмертного анализа

Кто-то в другом вопросе предложил использовать catch(...) получать всех в других отношениях необработанных - неожиданные/непредвиденные исключения путем окружения целого main() с try{}catch(...){} блок.

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

Сущность вопроса - то, какая информация может быть восстановлена тот путь (кроме любой отладки globals, я оставляю позади), и как восстановить его (как получить доступ и распознать независимо от того, что выгоду назвали с),

Кроме того, какие протесты соединены с ним. В особенности:

  • это будет играть по правилам с потоками тот росток позже?
  • разве это не повредит обработку segfaults (полученный в другом месте как сигнал)
  • разве это не будет влиять на другую попытку... ловят блоки, неизбежно вложенные внутри, которые являются там для обработки ожидаемых исключений?
14
задан SF. 2 February 2010 в 09:55
поделиться

6 ответов

Да, это хорошая идея.

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

Тогда возникает вопрос, что с ними делать.
Некоторые ОС (см. MS и SE) предоставляют некоторые дополнительные средства отладки, поэтому полезно просто повторно выбросить исключение после того, как вы его поймаете (потому что стек в любом случае был размотан).

int main()
{
    try
    {
        /// All real code
    }
    // I see little point in catching other exceptions at this point 
    // (apart from better logging maybe). If the exception could have been caught
    // and fixed you should have done it before here.

    catch(std::exception const& e)
    {
         // Log e.what() Slightly better error message than ...
         throw;
    }
    catch(...)   // Catch all exceptions. Force the stack to unwind correctly.
    {
        // You may want to log something it seems polite.
        throw;  // Re-throw the exception so OS gives you a debug opportunity.
    }
}
  • будет ли он хорошо работать с потоками, которые появятся позже?

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

Если вы говорите об исключениях в дочерних потоках. Опять же, это не очень хорошо определено (так что прочтите вашу документацию), но если поток завершается через исключение (то есть функция, используемая для запуска потока, завершается из-за исключения, а не возврата), то это обычно приводит к завершению работы приложения (такое же влияние как указано выше). Поэтому всегда лучше не допускать выхода из потока ВСЕХ исключений.

  • не нарушит ли он обработку segfaults (зафиксированных в другом месте как сигнал)

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

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

Не должно влиять на другие обработчики.

10
ответ дан 1 December 2019 в 13:33
поделиться

Насколько я помню, CALL (...) на Win32 ловит также исключения SEH, а вы не хотят , чтобы сделать это. Если вы получите исключение SEH, это потому, что произошло что-то очень страшно (в основном доступа к нарушениям), поэтому вы больше не можете доверять окружающей среде. Почти все, что вы могли бы сделать, может потерпеть неудачу с другим исключением SEH, поэтому даже не стоит пытаться. Более того, некоторые исключения SEH предназначены для того, чтобы быть пойманным системой; Больше на это здесь .

Итак, мой совет - использовать базовый класс исключения (например STD :: Исключение ) для всех ваших исключений, и поймайте только что введите «CAMALL»; Ваш код не может быть готов к решению другим видом исключения, поскольку они неизвестны по определению.

4
ответ дан 1 December 2019 в 13:33
поделиться

Вы можете попробовать решение, которое я использую , если вы делаете приложение .NET. Это отражает все необработанные исключения. Я вообще включаю в себя только код (с #iFndef Debug ) для производственного кода, когда я не использую отладчик.

Стоит указать, как указывает на указывание КГЯННАКАКИС, упоминание, что вы не можете захватить исключения в других потоках, но вы можете использовать одну и ту же схему Try-Chav в этих потоках и отправлять исключения обратно в основной нить, где вы можете перебросить их Чтобы получить полный след стека, что пошло не так.

1
ответ дан 1 December 2019 в 13:33
поделиться

Глобальный блок Try Catch полезен для производственных систем, чтобы не отобразить неприятное сообщение для пользователя. Во время развития я считаю, что лучше избежать.

Что касается ваших вопросов:

  • Я считаю, что глобальный слой Catch не будет ловить исключения в другом потоке. Каждый поток имеет собственное пространство стека.
  • Я не уверен в этом.
  • Вложенная попытка ... Компания блоки не влияют и будут выполняться как обычно. Исключение распространяется на стек, пока не найдет блок попробовать.
3
ответ дан 1 December 2019 в 13:33
поделиться

В C # (как и во многих других языках программирования) в этом случае следует использовать Заводские методы . Что-то вроде:

class TheForm
{
  public static TheForm CreateFromId(string idCode);
  public static TheForm CreateFromStatus(string status);
}

или параметры фантастики:

class TheForm
{
  public TheForm(string idCode, int);
  public TheForm(string status);
}

Или вы можете использовать Eiffel;):

class THE_FORM create
   make_from_id, make_from_status
feature
  ...
end
-121--4536241-

catch-all не будет ужасно полезным, так как нет информации типа/объекта, которую вы можете запросить. Однако если можно убедиться, что все исключения, созданные приложением, являются производными от одного базового объекта, можно использовать блок catch для базовой особой ситуации. Но тогда это было бы не все.

0
ответ дан 1 December 2019 в 13:33
поделиться

и способы его восстановления (как получить доступ к {{1 }} и распознать любой catch, который был вызван с помощью)

Если вы имеете в виду, как восстановить тип сгенерированного исключения, вы можете связать блоки catch для определенных типов (переходя от более конкретных к более общим) перед возврат к catch (...) :

try {
   ...
} catch (const SomeCustomException& e) {
   ...
} catch (const std::bad_alloc& e) {
   ...
} catch (const std::runtime_error& e) {
   // Show some diagnosic for generic runtime errors...
} catch (const std::exception& e) {
   // Show some diagnosic for any other unhandled std::exceptions...
} catch (...) {
   // Fallback for unknown errors.
   // Possibly rethrow or omit this if you think the OS can do something with it.
}

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

void MyExceptionHandler() {
   try {
      throw; // Rethrow the last exception.
   } catch (const SomeCustomException& e) {
      ...
   }
   ...
}

int main(int argc, char** argv) {
   try {
      ...
   } catch (...) {
      MyExceptionHandler();
   }
}
0
ответ дан 1 December 2019 в 13:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: