每个 C++ 开发者都应该了解关于 Structured Exceptions 的重要点是什么?
每个 C++ 开发者都应该了解关于 Structured Exceptions 的重要点是什么?
它们是Win32与Unix信号相当的东西,可以捕获诸如访问冲突、非法指令、除零等CPU异常。
使用正确的编译器选项(对于Visual C++是 /EHa),C++异常会使用与堆栈展开相同的机制,并且C++(用户)异常和SEH(操作系统)异常都能正常处理。
与C++异常不同,SEH没有类型,但所有SEH共享相同的数据结构,其中包含异常代码(原因)以及有关故障代码和CPU寄存器在故障时所保存内容的其他信息。有关此信息,请参见GetExceptionCode
和 GetExceptionInformation
。
此外,SEH还具有“first-chance”处理功能,允许您在展开销毁所有局部变量之前记录或以其他方式处理异常。
我最近遇到了一个问题,这个问题间接由SEH引起的,具体地说,是因为SEH的一个特性,我认为每个开发人员都应该知道:
当使用SEH时,析构函数不会被调用,因此如果你在析构函数中有清理代码,它将不会被清理。
我们的问题是由一个关键段包装器对象引起的,它在构造函数中带有Lock,在析构函数中带有Unlock。
我们遇到了死锁情况,无法弄清楚原因,在经过一周的代码查找、转储和调试后,我们终于明白了其中的原因:有一个异常被COM处理,导致临界区保持锁定状态。 我们在VS项目属性中更改了一个编译标志,告诉它即使对于SEH也要运行析构函数,这解决了问题。
因此,即使您的代码没有使用SEH,您可能正在使用一个使用SEH(如COM)的库,这可能导致意外的行为。
Win32™结构化异常处理深入解析是让您快速掌握SEH的参考文章,13年后仍然是最好的。
在MSDN上有一个专门介绍SEH与C++异常处理差异的主题。
当讨论SEH时,C++开发人员需要知道一些事情:
编写C/C++ SEH异常处理程序:
__try
{
// guarded code
}
__except ( expression )
{
// exception handler code
}
这不是C++异常处理,而是MS特定的扩展,用于直接钩入SEH。它与常见的C++异常有很大不同。要使用它们,您需要对SEH有很好的理解。
编写C/C++ SEH终止处理程序:Termination Handlers
__try {
// guarded code
}
__finally {
// termination code
}
和SEH处理程序一样,不要将其与C++异常语义混淆。您需要对SEH有很好的理解。
_set_se_translator
:这是将SEH异常转换为C++类型异常的函数,当使用异步异常/EHa时。
最后,个人意见:C++开发人员应该了解SEH吗?在第一个新手.ecxr之后,您就会明白,当推力到极限时,C++异常只是为您方便而提供的假象。唯一发生的事情就是SEH。
__finally
没有(expression)
。 - Abyx他们应该知道,它们不是标准C++的一部分-它们是微软的发明,可以用于其他语言。
为什么扩展程序的作者建议在大多数情况下不使用它?可能是因为该扩展程序是为C语言编写的,而当前环境是C ++。这些语言相似,因此将SEH移植到C ++作为副产品可能很容易,尽管只有“特定类型的程序”才能真正受益。(或者可能出于其他原因;也许移植是在C ++标准化之前开始的。历史变得复杂。)结构化异常处理(SEH)是Microsoft对C的扩展,用于优雅地处理某些异常代码情况,例如硬件故障。尽管Windows和Microsoft C ++支持SEH,但我们建议您使用ISO标准C ++异常处理,因为它使您的代码更具可移植性和灵活性。尽管如此,为了维护现有代码或特定类型的程序,您仍然可能需要使用SEH。