自研事后调试器:如何捕获未处理异常过滤器遗漏的异常?
事后调试器捕获未处理异常的机制,以及你的
UnhandledExceptionFilter未触发的原因 首先咱们得理清Windows异常处理的层级逻辑,这就能解释为什么WinDbg这类事后调试器能抓到你没捕获到的异常:
事后调试器的核心工作逻辑
事后调试器(比如WinDbg)并不依赖用户态的异常过滤机制,而是基于Windows内核级的错误报告体系——Windows Error Reporting (WER) 和调试子系统:
- 当一个异常经过所有用户态处理环节(包括SEH链、你设置的
UnhandledExceptionFilter)都无法被处理时,控制权会交给内核的异常调度器。 - 内核触发WER流程后,会检查系统注册表中的
HKLM\Software\Microsoft\Windows NT\CurrentVersion\AeDebug项(32位系统对应Wow6432Node下的同路径),如果配置了事后调试器(比如WinDbg的路径),就会启动该调试器并附加到崩溃进程上。 - 调试器通过Windows调试API(如
WaitForDebugEvent、ContinueDebugEvent)获取异常的完整上下文,此时它能捕获所有最终未被用户态处理的致命异常,不管中间有没有过SEH尝试处理但失败的情况。
为什么你的UnhandledExceptionFilter没触发mshtml中的AV?
你提到的mshtml.dll中Access Violation未触发自定义过滤器,但事后调试器弹出的情况,大概率是以下两种场景之一:
- mshtml内部SEH处理后直接触发系统崩溃:
mshtml这类系统模块有复杂的SEH结构,可能先捕获AV尝试恢复,但恢复失败后并没有将异常抛回用户态的UnhandledExceptionFilter,而是直接触发了系统级崩溃流程。这种情况下用户态过滤器不会被调用,但WER仍会启动事后调试器。 - 异常发生在系统托管线程中,绕过进程级过滤器:
mshtml会创建自己的工作线程,这些线程可能设置了局部异常处理逻辑,没有继承进程级的UnhandledExceptionFilter,或者在异常处理结束后直接终止线程,导致进程级过滤器没机会触发。
为什么AddVectoredExceptionHandler不是理想方案?
你说得完全正确,向量异常处理器(VEH)的触发时机在所有SEH之前,不管这个异常会不会被后续SEH处理并恢复程序执行。比如某个函数用SEH捕获AV并修复问题,程序继续正常运行,但VEH还是会被调用。这会导致你捕获大量“已处理”的异常,完全不符合你只抓“未处理异常”的目标。
替代方案建议
如果你想精准捕获所有未被用户态处理的异常,同时覆盖绕过UnhandledExceptionFilter的场景,可以考虑:
- 注册为系统事后调试器:修改AeDebug注册表项,把自己的调试器路径配置进去,逻辑和WinDbg完全一致,能捕获所有触发系统崩溃的异常。
- 编写轻量级调试器:通过
DebugActiveProcess附加到目标进程,监听EXCEPTION_DEBUG_EVENT,只处理那些最终导致进程终止的异常。
内容的提问来源于stack exchange,提问作者gedalia
相关产品推荐
相关产品推荐

