结构化异常处理(SEH)是 C 的Microsoft扩展,C++用于处理某些异常代码情况(如硬件故障)正常。 尽管 Windows 和 Microsoft C++支持 SEH,但我们建议在 C++ 代码中使用 ISO 标准C++异常处理。 它使代码更具可移植性和灵活性。 但是,若要维护现有代码或特定类型的程序,仍可能需要使用 SEH。
特定于Microsoft:
语法
try-except-statement:
__trycompound-statement__except(filter-expression)compound-statement
try-finally-statement:
__trycompound-statement__finallycompound-statement
注解
使用 SEH,可以确保在执行意外终止时正确释放资源(如内存块和文件)。 还可以通过使用不依赖 goto 语句或精心测试返回代码的简洁结构化代码来处理特定问题(例如内存不足)。
try-except本文中提到的语句try-finally是 C 和 C++ 语言的Microsoft扩展。 它们通过使应用程序能够在事件之后控制程序,从而支持 SEH,否则将终止执行。 尽管 SEH 适用于C++源文件,但它并非专为C++而设计。 如果在使用 /EHa 或 /EHsc 选项编译的C++程序中使用 SEH,将调用本地对象的析构函数,但其他执行行为可能不是预期的。 有关插图,请参阅本文后面的示例。 在大多数情况下,我们建议使用 ISO 标准 C++异常处理,而不是 SEH。 通过使用C++异常处理,可以确保代码更易于移植,并且可以处理任何类型的异常。
如果有使用 SEH 的 C 代码,则可以将其与使用C++异常处理C++代码混合使用。 有关信息,请参阅 C++中的句柄结构化异常。
有两种 SEH 机制:
异常处理程序或
__except块,这些处理程序可以根据值响应或消除异常filter-expression。 有关详细信息,请参阅try-except语句。无论异常是否导致终止,始终调用终止处理程序或
__finally块。 有关详细信息,请参阅try-finally语句。
这两种类型的处理程序是不同的,但通过称为 展开堆栈的进程密切相关。 发生结构化异常时,Windows 将查找当前处于活动状态的最新安装的异常处理程序。 处理程序可以执行以下三项作之一:
无法识别异常并将控制权传递给其他处理程序(
EXCEPTION_CONTINUE_SEARCH)。识别异常,但将其消除(
EXCEPTION_CONTINUE_EXECUTION)。识别异常并处理它(
EXCEPTION_EXECUTE_HANDLER)。
识别异常的异常处理程序可能不在发生异常时运行的函数中。 它可能位于堆栈上更高得多的函数中。 堆栈帧上的当前正在运行的函数和所有其他函数将终止。 在此过程中,堆栈将 解开。 也就是说,终止函数的局部非静态变量将从堆栈中清除。
在展开堆栈时,作系统会调用为每个函数编写的任何终止处理程序。 通过使用终止处理程序,可以清理因异常终止而保持打开状态的资源。 如果已输入关键部分,可以在终止处理程序中退出它。 程序关闭时,可以执行其他管家任务,例如关闭和删除临时文件。
后续步骤
示例:
如前所述,如果在C++程序中使用 SEH 并使用或/EHsc选项编译/EHa本地对象的析构函数。 但是,如果在使用C++异常,在执行期间的行为可能不是预期的行为。 此示例演示了这些行为差异。
#include <stdio.h>
#include <Windows.h>
#include <exception>
class TestClass
{
public:
~TestClass()
{
printf("Destroying TestClass!\n");
}
};
__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
printf("Throwing C++ exception\n");
throw std::exception("");
#else
printf("Triggering SEH exception\n");
volatile int *pInt = 0x00000000;
*pInt = 20;
#endif
}
__declspec(noinline) void TestExceptions()
{
TestClass d;
TestCPPEX();
}
int main()
{
__try
{
TestExceptions();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("Executing SEH __except block\n");
}
return 0;
}
如果用于 /EHsc 编译此代码,但本地测试控制宏 CPPEX 未定义, TestClass 则析构函数不会运行。 输出如下所示:
Triggering SEH exception
Executing SEH __except block
如果使用 /EHsc 编译代码并使用 CPPEX/DCPPEX (以便引发C++异常), TestClass 则析构函数将运行,输出如下所示:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
如果使用 /EHa 编译代码, TestClass 析构函数将执行是使用标准C++ throw 表达式还是 SEH 引发异常。 也就是说,是否 CPPEX 定义。 输出如下所示:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
有关详细信息,请参阅/EH(异常处理模型)。
特定于 END Microsoft