关于 C++ 中的结构化异常 (SEH),我应该了解什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2782915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:39:19  来源:igfitidea点击:

What should I know about Structured Exceptions (SEH) in C++?

c++exceptionexception-handlingsehstructured-exception

提问by Andrew T

What important points about Structured Exceptions should every C++ developer know?

每个 C++ 开发人员都应该知道关于结构化异常的哪些要点?

采纳答案by Ben Voigt

They are the Win32 equivalent to Unix signals, and let you catch CPU exceptions such as access violation, illegal instruction, divide by zero.

它们是等效于 Unix 信号的 Win32,让您捕获 CPU 异常,例如访问冲突、非法指令、除以零。

With the right compiler options (/EHa for Visual C++), C++ exceptions use the same mechanism as stack unwinding works properly for both C++ (user) exceptions and SEH (OS) exceptions.

使用正确的编译器选项(Visual C++ 的 /EHa),C++ 异常使用与堆栈展开相同的机制,对于 C++(用户)异常和 SEH (OS) 异常都正常工作。

Unlike C++ exceptions, SEH are not typed but all share the same data structure which has an exception code (the cause) and additional information on what code faulted and what the CPU registers held at the time of the fault. See GetExceptionCodeand GetExceptionInformationfor more details on this.

与 C++ 异常不同,SEH 没有类型化,但都共享相同的数据结构,该结构具有异常代码(原因)和关于发生故障的代码以及发生故障时 CPU 寄存器内容的附加信息。有关更多详细信息,请参阅GetExceptionCodeGetExceptionInformation

Also, SEH has "first-chance" handling, which allows you to log or otherwise handle the exception beforeunwinding destroys all the local variables.

此外,SEH 具有“第一次机会”处理,它允许您展开破坏所有局部变量之前记录或以其他方式处理异常。

回答by Tidhar

I recently had a problem which was caused indirectly by SEH, specifically because of one feature of SEH which I think every developer should be aware of:

我最近遇到了一个由 SEH 间接引起的问题,特别是因为 SEH 的一个特性,我认为每个开发人员都应该知道:

When SEH is used destructors are not called, so if you have cleanup code in your destructor it will not be cleaned up.

使用 SEH 时不会调用析构函数,因此如果析构函数中有清理代码,则不会清理它。

Our problem was caused by a Critical Section that was wrapped by an object with Lock in the constructor and Unlock in the destructor.

我们的问题是由一个临界区引起的,该临界区被构造函数中的 Lock 和析构函数中的 Unlock 的对象包装。

We had a deadlock situation and couldn't figure out why, and after about a week of digging through the code and dumps and debugging we finally understood it was because there was an exception that was handled by COM and causing the Critical section to stay locked. We changed a compilation flag in VS in the project properties which tell it to run destructors even for SEH and that solved the problem.

我们遇到了死锁情况,无法弄清楚原因,经过大约一周的代码挖掘、转储和调试后,我们终于明白这是因为存在由 COM 处理的异常并导致关键部分保持锁定状态. 我们在项目属性中更改了 VS 中的编译标志,该标志告诉它甚至为 SEH 运行析构函数,从而解决了问题。

So even though you may not use SEH in your code, you may be using a library that does (like COM) and that can cause unexpected behavior.

因此,即使您可能没有在代码中使用 SEH,您也可能使用了一个使用 SEH 的库(如 COM)并且可能导致意外行为。

回答by Tidhar

They should know that they are not part of Standard C++ - they are Microsoft invention and can be used in languages other than C++.

他们应该知道它们不是标准 C++ 的一部分——它们是 Microsoft 的发明,可以在 C++ 以外的语言中使用。

回答by Remus Rusanu

A Crash Course on the Depths of Win32? Structured Exception Handling

Win32 深度速成课程?结构化异常处理

That article is thereference on getting up to speed with SEH. 13 years later, is still the best there is.

那篇文章是了解SEH参考资料。13 年后,仍然是最好的。

There is a dedicated topic on MSDN for SEH vs. C++ Exception Handling Differences.

MSDN 上有一个关于SEH 与 C++ 异常处理差异的专门主题。

Some things a C++ developer should know if SEH is being discussed:

如果讨论 SEH,C++ 开发人员应该知道的一些事情:

Writing C/C++ SEH Exception Handlers:

编写 C/C++ SEH异常处理程序

__try 
{
   // guarded code
}
__except ( expression )
{
   // exception handler code
}

This is notC++ exception handling, is the MS specific extensions for hooking straight inot SEH. It works very differently from your run-of-the-mill C++ exceptions. You need a good understanding of SEH to use these.

不是C++ 异常处理,是用于挂钩直接 inot SEH 的 MS 特定扩展。它的工作方式与普通的 C++ 异常非常不同。您需要很好地了解 SEH 才能使用这些。

Writing C/C++ SEH Termination Handlers:

编写 C/C++ SEH终止处理程序

__try {
   // guarded code
}
__finally {
   // termination code
}

Same as with the SEH handler, do not confuse this with C++ exception semantics. You need a good understanding of SEH.

与 SEH 处理程序相同,不要将其与 C++ 异常语义混淆。您需要对 SEH 有很好的了解。

_set_se_translator: this is the function that translates SEH exceptions into C++ type exceptions when asynchronous exceptions are used /EHa.

_set_se_translator: 这是在使用异步异常时将 SEH 异常转换为 C++ 类型异常的函数/EHa

And finally, a personal opinion: should a C++ developer know SEH? After your first rookie .ecxryou'll understand that when the push come to shove C++ exceptions are just an illusion provided for your convenience. The only thing going on is SEH.

最后,个人意见:C++ 开发人员是否应该了解 SEH?在您使用第一个新手.ecxr 之后,您就会明白,当迫不得已时,C++ 异常只是为了您的方便而提供的一种错觉。唯一发生的事情是SEH。

回答by JaMiT

An important point is knowing when to use SEH and when to use standard C++ exceptions. First, choose only one system – mixing systems tends to be problematic, requiring a deep understanding of both to implement well. Second, at a high level, SEH is not limited to C++, while standard C++ exceptions are not limited to Windows. If this does not dictate your decision, choose standard exceptions unless they are inadequate (see the other answers for more details about what SEH can do).

重要的一点是知道何时使用 SEH 以及何时使用标准 C++ 异常。首先,只选择一个系统——混合系统往往有问题,需要对两者都有深入的了解才能很好地实施。其次,在高层次上,SEH 不限于 C++,而标准 C++ 异常不限于 Windows。如果这不能决定您的决定,请选择标准例外,除非它们不合适(有关 SEH 可以做什么的更多详细信息,请参阅其他答案)。

A quote from Microsoft's documentation(dated 08/13/2018) supports this conclusion.

来自Microsoft 文档(日期为 08/13/2018)的引述支持这一结论。

Structured exception handling (SEH) is a Microsoft extension to C to handle certain exceptional code situations, such as hardware faults, gracefully. Although Windows and Microsoft C++ support SEH, we recommend that you use ISO-standard C++ exception handling because it makes your code more portable and flexible. Nevertheless, to maintain existing code or for particular kinds of programs, you still might have to use SEH.

结构化异常处理 (SEH) 是 Microsoft 对 C 的扩展,用于优雅地处理某些异常代码情况,例如硬件故障。尽管 Windows 和 Microsoft C++ 支持 SEH,但我们建议您使用 ISO 标准的 C++ 异常处理,因为它使您的代码更具可移植性和灵活性。尽管如此,为了维护现有代码或特定类型的程序,您可能仍然必须使用 SEH。

Why would the author of an extension recommend it not be used in most cases? Presumably because the extension was written for C and the current context is C++. The languages are similar, so porting SEH to C++ as a side-benefit was probably easy enough, even though only "particular kinds of programs" would truly benefit. (Or possibly some other reason; maybe the porting was started before C++ was standardized. History gets convoluted.)

为什么扩展的作者会建议在大多数情况下不要使用它?大概是因为扩展是为 C 编写的,当前上下文是 C++。这些语言是相似的,因此将 SEH 作为附带好处移植到 C++ 可能很容易,即使只有“特定类型的程序”才能真正受益。(或者可能是其他一些原因;也许移植是在 C++ 标准化之前开始的。历史变得错综复杂。)