处理异常
操作系统使用结构化异常处理来向某些类型的错误发出信号。 驱动程序调用的例程可能会引发驱动程序必须处理的异常。
系统会捕获以下常规类型的异常:
硬件定义的故障或陷阱,例如,
- 访问冲突 (请参阅以下)
- 数据类型不对齐 (,例如在奇字节边界上对齐的 16 位实体)
- 非法和特权指令
- (尝试在代码) 的互锁节内执行无效指令序列的锁序列无效
- 整数除以零和溢出
- 浮点除以零、溢出、下溢和保留操作数
- 支持调试器的断点和单步执行 ()
系统软件定义的异常,例如,
- (尝试在保护页内某个位置加载或存储数据)
- 页面读取错误 (尝试将页面读取到内存中,并遇到并发 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。 导致引发异常的驱动程序必须处理它:较低级别的驱动程序不能依赖较高级别的驱动程序来处理异常。
驱动程序可以使用 ExRaiseAccessViolation、 ExRaiseDatatypeMisalignment 或 ExRaiseStatus 例程直接引发异常。 驱动程序必须处理这些例程引发的任何异常。
下面是部分例程列表,这些例程至少在某些情况下可能会引发异常:
对用户模式缓冲区的内存访问也可能导致访问冲突。 有关详细信息,请参阅 引用User-Space地址中的错误。
请注意,结构化异常处理不同于 C++ 异常。 内核不支持 C++ 异常。
有关结构化异常处理的详细信息,请参阅Microsoft Windows SDK和 Visual Studio 文档。