为什么不使用function-try-block声明main()?

问题描述:

a few SO posts关于是否声明main()使用函数尝试块语法valid syntax,并且普遍的共识似乎是它是完全有效的。这让我想知道...是否有任何理由(性能,风格,线程同步,多线程)为什么一个不会使用此语法作为main()作为一般规则以更优雅地捕获任何未处理的异常?为什么不使用function-try-block声明main()?

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

+6

对于初学者,您可以在普通函数体中使用普通的try/catch,而不会混淆不知道此语法的人。 –

+0

与简单的try/catch相比有什么优势 – 2017-10-16 19:58:29

+1

函数try块主要用于构造函数,因此您可以捕获在初始化程序列表中抛出的异常。 –

如果碰巧有一个想要在catch块中访问的变量,则需要使用大括号来提供可见性。但即使这样可以用嵌套try/catch来处理......

如果你捕捉到(否则)未捕获的对象,你将无法通过检查堆栈跟踪来找出执行到达抛出的方式,因为当异常处理程序执行时,堆栈已经被解除。

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

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

此外,有些情况下,catch块无法处理异常。例如,当你抛出一个正在执行的析构函数时,抛出一个异常。因此,为了处理这些“不可捕捉”的异常,无论如何您都需要终止处理程序,所以在未捕获异常情况下重复功能几乎没有优势。


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

您可以轻松地转换

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

int realMain() 
{ 
    // The real code of main 
} 

int main() 
{ 
    try 
    { 
     return realMain(); 
    } 
    catch (...) 
    { 
    } 
} 

不失功能/行为。

我会猜测你使用第一版还是第二版是一个团队编码实践的问题。从编译器和运行时间的角度来看,我没有看到任何语义差异。

为什么人会不会使用这个语法的main()作为一般规则赶上 任何未处理的异常的任何地方更优雅?与C

    1. 兼容性有时也没有办法更加妥善地处理未处理的异常。

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

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

    例如,在我的情况,我想给用户

    好提供支持电子邮件地址,你打算怎么做,在一个服务器没有面向用户界面?

    实际上,即使在面向用户的组件中,如果您无法告诉catch块中它们处于什么状态,您将如何执行该操作?

    而对于那些无法向用户显示任何有用信息的过程(或者首先没有任何“用户”概念),您会在catch块中做什么比默认terminate

    至于

    ...比特定于操作系统的默认处理更多的信息.​​..

    许多操作系统的默认行为将保存过程执行状态的完整快照,在未处理的异常被抛出的时候,将其发送到文件进行调试。作为开发人员,我想不出许多默认行为,这些行为可能是更多信息。

    不可否认,我更喜欢作为桌面应用程序的最终用户更精美的东西,但这是C++程序的一个非常小的子集。