为什么不使用函数try块声明main()?



有一些SO帖子关于使用函数try-block语法声明main()是否是有效语法,普遍的共识似乎是它完全有效。这让我想。。。有什么原因(性能、风格、线程同步、多线程)让main()的此语法作为一条通用规则,以便更优雅地捕捉任何未处理的异常?

显然,理想情况下不会有未处理的异常,但它们会发生,我认为提供比操作系统特定的默认处理程序更具信息性的东西会很好。例如,在我的情况下,我想向用户提供一个支持电子邮件地址,这样他们就可以报告崩溃,并让我的程序向我的基于云的崩溃日志提交日志。

例如,在我的情况下,我想向用户提供一个支持电子邮件地址

好吧,在没有面向用户界面的服务器中,你将如何做到这一点?

事实上,即使在带有面向用户组件的过程中,如果您无法在catch块中判断它们处于什么状态,您将如何做到这一点?

而且,对于那些你不能向用户显示任何有用的东西(或者一开始就没有任何"用户"的概念)的过程,你会在你的catch块中做什么比默认的terminate更好?

对于

。。。比操作系统特定的默认处理程序更具信息性。。。

许多操作系统的默认行为是在抛出未处理的异常时,将进程执行状态的完整快照保存到文件中进行调试。作为开发人员,我想不出有多少默认行为会提供更多信息。

诚然,作为桌面应用程序的最终用户,我更喜欢更精致的东西,但这只是C++程序的一小部分。

您可以轻松转换

int main() try {
// The real code of main
}
catch (...)
{
}

int realMain()
{
// The real code of main
}
int main()
{
try
{
return realMain();
}
catch ( ... )
{
}
}

而不会失去功能/行为。

我想,您是使用第一个版本还是使用第二个版本取决于团队的编码实践。从编译器和运行时的角度来看,我没有看到任何语义差异。

如果您碰巧在catch块中有一个要访问的变量,则需要大括号来提供可见性。但即便如此,也可以使用嵌套的try/catch。。。

为什么不将main()的语法用作捕获有没有更优雅的未处理异常?

  1. 与C
  2. 有时无法更优雅地处理未处理的异常

显然,理想情况下不会出现未处理的异常,但它们发生了,我认为提供一些更具信息性的东西会很好而不是操作系统特定的默认处理程序。例如,在我的情况下,我会喜欢向用户提供支持电子邮件地址,以便他们可以报告崩溃,并让我的程序向我的基于云的崩溃提交日志日志

如果发生意外异常,您无法确定是否可以正确处理。如果您的示例中出现网络错误异常,您将如何处理。尝试发送电子邮件会导致另一个异常吗?当你不能确定你的数据没有被破坏,并且你不能确定在这个错误之后你的程序可以正确运行时,可能会有其他错误。所以,如果你不知道发生了什么错误,最好让你的程序崩溃。您可以实现另一个"观察者"服务,该服务检查进程是否正在运行,如果它已经崩溃,它可以向用户发送带有日志和核心转储的电子邮件。

如果捕获(否则)未捕获的对象,您将无法通过检查堆栈跟踪来了解执行是如何到达抛出的,因为当执行异常处理程序时,堆栈已经展开。

如果您让意外异常不被捕获,您可能能够在终止处理程序中检查堆栈跟踪-这不是标准所保证的,但这也不是什么大不了的,因为也没有标准的方法来检查堆栈跟踪(在C++中)。您可以在程序中使用特定于平台的API,也可以使用外部调试器进行检查。

因此,例如,在您的情况下,不捕获异常的好处是,您可以将堆栈跟踪附加到要提交的日志条目。

此外,在某些情况下,catch块无法处理异常。例如,当您从因抛出异常而执行的析构函数中抛出时。因此,要处理这些"不可捕获"的异常,无论如何都需要一个终止处理程序,因此在未捕获异常的情况下复制功能几乎没有什么好处。


至于用于捕获异常的语法,没有区别。函数try块不同的情况是构造函数,它允许捕获子对象构造函数抛出的异常。

最新更新