处理异常

操作系统使用结构化异常处理来向某些类型的错误发出信号。 驱动程序调用的例程可能会引发驱动程序必须处理的异常。

系统会捕获以下常规类型的异常:

  1. 硬件定义的故障或陷阱,例如,

    • 访问冲突 (请参阅以下)
    • 数据类型不对齐 (,例如在奇字节边界上对齐的 16 位实体)
    • 非法和特权指令
    • (尝试在代码) 的互锁节内执行无效指令序列的锁序列无效
    • 整数除以零和溢出
    • 浮点除以零、溢出、下溢和保留操作数
    • 支持调试器的断点和单步执行 ()
  2. 系统软件定义的异常,例如,

    • (尝试在保护页内某个位置加载或存储数据)
    • 页面读取错误 (尝试将页面读取到内存中,并遇到并发 I/O 错误)

访问冲突是尝试在当前页面保护设置下不允许的页面上执行操作。 在以下情况下会发生访问冲突:

  • 读取或写入操作无效,例如写入只读页面。

  • 若要访问超出当前程序地址空间限制的内存, (称为长度冲突) 。

  • 访问当前驻留但专用于使用系统组件的页面。 例如,不允许用户模式代码访问内核正在使用的页面。

如果操作可能导致异常,驱动程序应将操作包含在 try/except 块中。 在用户模式下访问位置是异常的典型原因。 例如, ProbeForWrite 例程检查驱动程序是否实际可以写入用户模式缓冲区。 如果不能,例程将引发STATUS_ACCESS_VIOLATION异常。 在下面的代码示例中,驱动程序在 try/except 中调用 ProbeForWrite,以便它可以处理生成的异常(如果应该发生)。

try {
    ...
    ProbeForWrite(Buffer, BufferSize, BufferAlignment);
 
    /* Note that any access (not just the probe, which must come first,
     * by the way) to Buffer must also be within a try-except.
     */
    ...
} except (EXCEPTION_EXECUTE_HANDLER) {
    /* Error handling code */
    ...
}

驱动程序必须处理任何引发的异常。 未处理的异常会导致系统检查 bug。 导致引发异常的驱动程序必须处理它:较低级别的驱动程序不能依赖较高级别的驱动程序来处理异常。

驱动程序可以使用 ExRaiseAccessViolationExRaiseDatatypeMisalignmentExRaiseStatus 例程直接引发异常。 驱动程序必须处理这些例程引发的任何异常。

下面是部分例程列表,这些例程至少在某些情况下可能会引发异常:

对用户模式缓冲区的内存访问也可能导致访问冲突。 有关详细信息,请参阅 引用User-Space地址中的错误

请注意,结构化异常处理不同于 C++ 异常。 内核不支持 C++ 异常。

有关结构化异常处理的详细信息,请参阅Microsoft Windows SDK和 Visual Studio 文档。