结构化异常处理 (C/C++)

结构化异常处理(SEH)是 C 的Microsoft扩展,C++用于处理某些异常代码情况(如硬件故障)正常。 尽管 Windows 和 Microsoft C++支持 SEH,但我们建议在 C++ 代码中使用 ISO 标准C++异常处理。 它使代码更具可移植性和灵活性。 但是,若要维护现有代码或特定类型的程序,仍可能需要使用 SEH。

特定于Microsoft:

语法

try-except-statement
__try compound-statement __except ( filter-expression ) compound-statement

try-finally-statement
__try compound-statement __finally compound-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 机制:

这两种类型的处理程序是不同的,但通过称为 展开堆栈的进程密切相关。 发生结构化异常时,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

另请参阅

异常处理
关键字
<exception>
错误和异常处理
结构化异常处理 (Windows)