捕获主要(...)中的异常是否有意义?

时间:2008-12-15 12:14:35

标签: c++ exception exception-handling

我在项目中找到了一些看起来像这样的代码:

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 个答案:

答案 0 :(得分:16)

如果未捕获异常,则标准不会定义堆栈是否已展开。因此,在某些平台上将调用析构函数,而在其他平台上,程序将立即终止。在顶层捕获可确保始终调用析构函数。

所以,如果你没有在调试器下运行,那么抓住所有东西可能是明智的:( ...)以及std :: exception。然后,即使是致命的异常,您的应用程序代码也可以使用RAII进行清理。在许多这样的情况下,您实际上并不需要清理,因为操作系统会为您完成。但是,例如,您可能希望尽可能干净地与远程服务断开连接,并且可能存在流程外部的资源,例如命名管道/互斥体,您更愿意销毁而不是泄漏。

在主要情况下重新抛出异常在我看来是有限的用途,因为你已经失去了它最初抛出的上下文。我认为在调试器中捕获未捕获的异常比仅将故障记录到std :: cerr更嘈杂,因此如果有可能错过记录,则重新抛出将是明智之举。

如果您希望调试器在调试模式下捕获意外情况,在发布模式下会抛出最终导致退出的异常,那么还有其他方法可以做到这一点,而不是让异常未被捕获,以便调试器看到它​​。例如,您可以使用assert宏。当然,这对于意外和不可预测的情况没有帮助,例如,如果您在.NET上使用SEH,则会出现硬件异常。

答案 1 :(得分:6)

为什么说打印出异常?这不是C ++运行时的典型行为。充其量,您可以期望打印出它的类型。

此外,该程序保留“失败”状态,而异常可能导致终止中止状态(即退出代码中指示的信号)。

答案 2 :(得分:6)

main函数中的try-catch隐藏了调试器的异常。我会说,这不好。

另一方面,客户不应该有调试器,因此捕获异常很好。这很好。

就个人而言,我在构建发布版本时捕获main函数中的所有异常,并且在构建调试配置时我不这样做。

答案 3 :(得分:5)

堆栈未解除的情况的简单示例:
Why destructor is not called on exception?

异常可能导致应用程序终止而不是展开堆栈的情况列表 Why destructor is not called on exception?

如果没有在任何级别捕获异常并且将转义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的构造函数中粘贴断点。

答案 4 :(得分:3)

这是一个全局捕获块。显示一个很好的用户理解的消息('内部错误')而不是一个神秘的异常打印输出是很常见的。这可能在特定的代码块中并不明显,但通常是一个好主意。

答案 5 :(得分:0)

根据Windows规范,main不允许抛出。 (实际上它会导致询问您是否要将错误报告发送给Microsoft的消息)

答案 6 :(得分:0)

看一下C ++圣经,即Stroustrup,他有一个例子,它也在Applied C ++编程中重复。理由是:

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