11

我在一个项目中发现了一些代码,看起来像这样:

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

我不明白为什么要捕获异常。如果不是,应用程序将简单地退出并打印异常。

您认为有什么好的理由在这里捕获异常吗?


编辑:我同意打印异常错误是件好事。但是,重新抛出异常不是更好吗?我有一种感觉,我们在这里吞下了它……

4

7 回答 7

16

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

因此,如果您不在调试器下运行,那么捕获所有内容可能是明智之举:(...) 以及 std::exception。然后,即使出现致命异常,您的应用程序代码也可以使用 RAII 进行清理。在许多此类情况下,您实际上不需要清理,因为操作系统会为您完成。但是例如,您可能更愿意在可能的情况下完全断开与远程服务的连接,并且可能存在进程外部的资源,例如命名管道/互斥锁,您更愿意破坏而不是泄漏。

在我看来,在 main 中重新抛出异常的用处有限,因为您已经丢失了最初抛出异常的上下文。我认为在调试器中捕获未捕获的异常比仅将故障记录到 std::cerr 更嘈杂,因此如果有可能丢失日志记录,则重新抛出将是明智之举。

如果您希望调试器在调试模式下捕获意外情况,在发布模式下会引发异常并最终导致退出,那么除了不捕获异常以便调试器看到它​​之外,还有其他方法可以做到这一点。例如,您可以使用断言宏。当然,如果您在 .NET 上使用 SEH,这对于意外和不可预测的情况(例如硬件异常)无济于事。

于 2008-12-15T12:57:27.060 回答
6

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

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

于 2008-12-15T12:17:43.397 回答
6

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

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

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

于 2008-12-15T12:22:48.923 回答
5

堆栈未展开的情况的一个简单示例:
为什么在异常时不调用析构函数?

异常可能导致应用程序终止而不是展开堆栈的情况列表。
为什么异常时不调用析构函数?

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

于 2008-12-15T15:42:15.823 回答
3

这是一个全局 catch 块。显示一个很好且用户理解的消息(“内部错误”)而不是神秘的异常打印输出是很常见的。这可能从特定的代码块中看不出来,但总的来说这是一个好主意。

于 2008-12-15T12:20:19.570 回答
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
     {
     }
}
于 2008-12-15T12:29:06.400 回答
0

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

于 2012-08-06T09:35:36.830 回答