控制异常和事件
在用户模式和内核模式应用程序中有很多方法用于截获和处理异常。激活的调试器、即时调试器或内部的错误处理程序都是异常处理的通常方法。
关于这些错误处理方式优先等级的更多信息,查看启用即时调试。
当Microsoft Windows操作系统允许由调试器来处理异常时,产生异常的程序会中断到调试器。即应用程序停止运行而调试器被激活。之后,调试器可以用各种方式处理掉异常或者分析情况。最后,调试器可以结束进程或恢复它的执行。
如果调试器跳过异常并继续程序执行,操作系统如同没有附加调试器一样会查找其他异常处理器。如果异常被处理掉,则程序继续运行。但是,如果异常仍然没有处理,系统会给予调试器第二次处理机会。
使用调试器分析异常
当异常或事件中断到调试器时,可以用调试器检查被执行的代码或者查看进程内存。通过修改某些值或者跳转到程序的另一个位置,可能可以解决掉这个异常。
使用gh (Go with Exception Handled) 或 gn (Go with Exception Not Handled) 命令恢复程序执行。
如果在调试器的第二次异常处理机会时使用gn 命令,则程序被终止。
内核模式异常
内核模式代码产生的异常比用户模式异常要更加严重。如果内核模式异常没有被处理,则会产生bug check并且系统停止。
和用户模式异常一样,如果有内核调试器附加到系统上,在错误检查屏幕(即蓝屏)产生前,会先通知调试器。如果没有附加调试器,则直接蓝屏。这种情况下,系统可能会创建崩溃转储文件。
从调试器控制异常和事件
可以设置调试器处理异常和事件的方式。
调试器可以为每个异常或事件设置中断方式:
- 事件发生时直接中断到调试器("第一次处理机会")。
- 在其他错误处理器已经接收到处理机会之后。("第二次处理机会")。
- 在发生事件时发送一条信息到调试器,但是继续执行。
- 调试器跳过事件。
调试器也可以为每个异常和事件设置处理方式。调试器可以将事件当作已处理异常或未处理异常来对待。(当然,并不是实际出错的事件是不需要处理的。)
可以用如下方法来控制中断方式和处理方式:
- 在调试器命令窗口使用SXE、 SXD、 SXN或SXI 命令。
- (仅CDB)在CDB 命令行中使用-x、 -xe、-xd、-xn或-xi 选项。
- (仅CDB) 在Tools.ini 文件中使用sxe 或 sxd 关键字。
- (仅WinDbg) 在Debug菜单点击 Event Filters 打开Event Filters 对话框,并进行需要的配置。
SX*命令、-x* 命令行选项和sx* Tools.ini 关键字用于设置特定事件的中断方式。添加-h 选项来设置事件的处理方式。
有4个特殊的事件代码(cc, hc, bpec, 和ssec)只能指定处理方式。
使用.lastevent (Display Last Event) 命令显示最近一次异常或事件。
控制中断方式
为异常或事件设置中断方式可以使用以下选项。
|
命令 |
条件名 |
说明 |
|
SXE 或 -xe |
Break (Enabled) |
当异常发生时,目标立即中断到调试器。该中断在其他任何错误处理器被调用之前。这种方法称为第一次异常处理。 |
|
SXD |
Second chance break |
调试器不会在第一次异常处理机会时中断(虽然会显示一条信息)。如果其他错误处理其不能处理异常,则目标停止执行并中断到调试器。这种方法称为第二次异常处理。 |
|
SXN |
Output |
当异常产生时,目标应用程序不会中断到调试器。但是,调试器中会显示一条有关的信息。 |
|
SXI |
Ignore |
异常发生时,目标程序不会中断带调试器,并且不会显示信息。 |
如果某个异常预先没有使用SX* 设置过,则目标进程在第二次机会时中断到调试器。所有事件的默认方式在下面的"事件定义和默认设置"主题中列出。
使用WinDbg图形界面设置中断方式,可以在Debug菜单打开Event Filters ,并在Event Filters 对话框中点击要设置的事件,并选择Enabled、Disabled、Output或Ignore。
控制处理方式
除非使用gh (Go with Exception Handled) 命令,否则所有事件都不会被处理。
所有异常都不会被处理,除非使用了sx* 命令和-h选项。
另外,SX* 选项可以配置非法句柄、STATUS_BREAKPOINT 中断指令和单步异常的处理方式。 (这个配置和他们的中断配置是分开的。)配置中断方式时,这些事件分别名为 ch、bpe和sse。在配置异常处理方式时,他们分别名为hc、bpec和ssec (完整的事件列表,查看下面的"事件定义和默认设置"节。)
CTRL+C 事件(cc)可以配置处理方式,但是没有中断方式。如果程序接收到了CTRL+C事件,总是会中断到调试器。
当为cc、 hc、 bpec和 ssec 事件使用SX*命令,或对某个异常将SX* 和-h 选项一起使用时,会遇到下面一些情况。
|
命令 |
方式 |
说明 |
|
SXE |
Handled |
重新开始执行时事件已被处理。 |
|
SXD, |
Not Handled |
重新开始执行时事件未被处理。 |
使用WinDbg图形界面设置中断方式,可以在Debug菜单打开Event Filters ,并在Event Filters 对话框中点击要设置的事件,并选择Handled 或Not Handled。
自动命令
调试器允许设置一些命令用于当事件或异常中断到调试器时自动执行。可以分别为第一次异常处理和第二次异常处理设置一个命令字符串。使用SX* 命令或Debug | Event Filters 菜单命令设置。每个命令字符串可以包含用分号隔开的数条命令。
不管中断方式如何,这些命令都会被执行。换句话说,即使中断方式为"Ignore",命令仍然会被执行。如果中断方式为"第二次处理机会",则第一次处理机会的命令在异常第一次发生时,调用任何其他处理程序前被执行。命令字符串可以以运行命令结尾,如g (Go), gh (Go with Exception Handled)或gn (Go with Exception Not Handled)。
事件定义和默认设置
可以修改以下这些异常的中断方式和处理方式。下表同时指明了他们的默认中断方式。
以下异常的默认处理方式都是"Not Handled"。修改这些方式时要特别小心。如果将方式修改为"Handled",则所有第一次异常和第二次异常都被认为是已处理,原有的所有异常处理函数都会被跳过。
|
事件代码 |
含义 |
默认中断方式 |
|
asrt |
断言错误(Assertion failure) |
中断(Break) |
|
av |
访问违例(Access violation) |
Break |
|
dm |
数据未对齐(Data misaligned) |
Break |
|
dz |
除零(Divide by zero) |
Break |
|
eh |
C++ EH异常(C++ EH exception) |
Second-chance break |
|
gp |
页保护违例(Guard page violation) |
Break |
|
ii |
非法指令(Illegal instruction) |
Second-chance break |
|
iov |
整数溢出(Integer overflow) |
Break |
|
ip |
页面I/O错误(In-page I/O error) |
Break |
|
isc |
非法系统调用(Invalid system call) |
Break |
|
lsq |
非法加锁次序(Invalid lock sequence) |
Break |
|
sbo |
栈缓冲区溢出(Stack buffer overflow) |
Break |
|
sov |
栈溢出(Stack overflow) |
Break |
|
wkd |
唤醒调试器(Wake debugger) |
Break |
|
aph |
应用程序挂起(Application hang) |
Break |
|
3c |
子程序终止(Child application termination) |
Second-chance break |
|
ch |
非法句柄(Invalid handle) |
Break |
|
Number |
所有编号的异常(Any numbered exception) |
Second-chance break |
注意 可以使用ah (Assertion Handling)命令覆盖指定地址的asrt 中断方式。ch 和hc 事件是同一个异常。控制中断方式时,使用sx* ch;控制异常处理方式时,使用sx* hc。
可以修改以下这些异常的中断方式和处理方式。下表同时指明了他们的默认中断方式。
以下异常的默认处理方式都是"Handled"。由于这些异常是用来和调试器通信的,所以一般不能把它们设置为"Not Handled",否则调试器会跳过这些异常并由其他异常处理器来处理。
应用程序可以使用DBG_COMMAND_EXCEPTION (dbce) 来和调试器通信。这个异常类似断点,但是可以使用SX*命令来指定该异常发生时的对待方式。
|
事件代码 |
含义 |
默认中断方式 |
|
dbce |
专用调试器命令异常(Special debugger command exception) |
跳过(Ignore) |
|
vcpp |
专用Virtual C++异常(Special Visual C++ exception) |
Ignore |
|
wos |
WOW64单步异常(WOW64 single-step exception) |
Break |
|
wob |
WOW64断点异常(WOW64 breakpoint exception) |
Break |
|
sse |
单步异常(Single-step exception) |
Break |
|
bpe |
断点异常(Breakpoint exception) |
Break |
|
cce |
CTRL+C 或CTRL+BREAK 当目标程序是控制台程序并输入了CTRL+C或CTRL+BREAK。 |
Break |
注意 上表中最后三个异常有两个不同的事件代码。控制中断方式时,使用 sse, bpe, 和cce。控制异常处理方式时,使用ssec, bpec和 cc。
可以修改下面这些事件的中断方式。由于他们不是异常,所以和异常处理方式无关。
|
事件代码 |
含义 |
默认中断方式 |
|
ser |
系统错误(System error) |
Ignore |
|
cpr[:Process] |
创建进程(Process creation) 当通过CDB的-o 命令行选项或 WinDbg .childdbg (Debug Child Processes) 命令启用子进程调试时,该事件才可控制。进程名可以包含任意扩展名和星号(*)、问号(?)通配符。 |
Ignore |
|
epr[:Process] |
进程退出(Process exit) 当通过CDB的-o 命令行选项或 WinDbg .childdbg (Debug Child Processes) 命令启用子进程调试时,该事件才可控制。进程名可以包含任意扩展名和星号(*)、问号(?)通配符。 |
Ignore |
|
ct |
线程创建(Thread creation) |
Ignore |
|
et |
线程退出(Thread exit) |
Ignore |
|
ld[:Module] |
加载模块(Load module) |
输出(Output) |
|
ud[:Module] |
卸载模块(Unload module) |
Output |
|
out[:Output] |
目标程序输出(Target application output) |
Ignore |
|
ibp |
初始断点(Initial break point) |
用户模式:Break。可以使用-g 命令行选项将这个方式修改为"Ignore" |
|
iml |
初始模块加载(Initial module load) |
Ignore。可以通过几种方法设置为"Break" 关于修改该方式的更多信息,查看崩溃和重起目标机。 |
本文介绍在用户模式和内核模式应用程序中如何截获和处理异常。包括如何使用调试器分析异常,设置异常处理的优先级,以及如何配置调试器响应不同类型的异常。
2万+

被折叠的 条评论
为什么被折叠?



