我正在调试游戏,经常遇到异常(EXCEPTION_PRIV_INSTRUCTION)
调试器在它停止的地址上暂停,现在我想一次跳过一个命令,但是当我跳过它时不会一次执行一个命令
我正在调试游戏,经常遇到异常(EXCEPTION_PRIV_INSTRUCTION)
调试器在它停止的地址上暂停,现在我想一次跳过一个命令,但是当我跳过它时不会一次执行一个命令
例外是复杂的业务。我将尝试简要解释 Windows 中的 SEH(结构化异常处理)如何调用适当的异常处理程序。但是,您的游戏可能不使用 SEH,因为您的问题太宽泛,所以我的回答是。我以 SEH 为基础,因为它最容易理解,而且您可以按照自己的方式工作。
有硬件和软件例外。硬件异常由 CPU 抛出 - 例如非法内存访问、除以 0...
软件异常(由例如throw
在 C++ 中使用RaiseException
Windows 下的调用引起(请参阅 MSDN)。
操作系统存储一个异常处理程序列表——一个可以处理异常的例程列表。这些例程通常是您的catch
块中的指令。每个例程在被调用时确定它是否不想处理异常。如果您的例程决定不处理异常,它会告诉操作系统继续查找。
处理程序列表存储在线程信息块 (TIB) 中:
_NT_TIB:
+0x000 ExceptionList
+0x004 StackBase
+0x008 StackLimit
+0x00C SubSytemTib
+0x010 FiberData
+0x010 Version
+0x014 ArbitaryUserPointer
+0x018 Self
TIB 可在FS:[0]
。
该ExceptionList
字段是当前线程的异常处理程序列表的头部。
该列表是一个_EXCEPTION_REGISTRATION_RECORD
结构链:
_EXCEPTION_REGISTRATION_RECORD
+0x000 Next
+0x004 Handler
如何调度异常(页面错误示例)
处理器产生一个页面错误中断INT 0x0E
并调用[IDT+0x0E]
. 在 Windows 中,这通常是KiTrap0E
.
然后,Windows调用到用户模式异常调度程序例程KiUserExceptionDispatcher
在NTDLL.DLL
。
调度程序然后调用RtlDispatchException
其中遍历ExceptionList
.
您可以从上面看到为什么您的程序会跳来跳去并且您无法逐行跟踪它 - 当发生异常时,处理器本身会调用KiTrap0E
- 您看不到该调用。然后当处理程序被调用时,也会有很多“跳跃”——该RtlDispatchException
函数遍历所有注册的异常处理程序。您需要找到适当的处理程序并查看您的游戏对您的异常做了什么。