在源模式下调试

如果可以分析代码的源,而不是反汇编二进制文件,则调试应用程序会更容易。

如果源语言为 C、C++ 或程序集,则 WinDbg、CDB 和 KD 可以在调试中使用源代码。

编译要求

若要使用源调试,必须在生成二进制文件时让编译器或链接器创建符号文件 (.pdb 文件) 。 这些符号文件显示调试器二进制指令与源行的对应方式。

此外,调试器必须能够访问实际的源文件,因为符号文件不包含实际的源文本。

如果可能,编译器和链接器不应优化代码。 如果代码已优化,则源调试和对局部变量的访问更加困难,有时几乎是不可能的。 如果使用生成实用工具作为编译器和链接器,请将MSC_OPTIMIZATION宏设置为 /Od /Oi 以避免优化。

查找符号文件和源文件

若要在源模式下调试,调试器必须能够查找源文件和符号文件。 有关详细信息,请参阅 源代码

开始源调试

每当调试器具有当前正在调试的线程的正确符号和源文件时,调试器都可以显示源信息。

如果使用调试器启动新的用户模式应用程序,Ntdll.dll加载应用程序时将发生初始中断。 由于调试器无权访问Ntdll.dll源文件,因此此时无法访问应用程序的源信息。

若要将程序计数器移动到应用程序的开头,请在入口点处将断点添加到二进制文件。 在 “调试器命令”窗口中,键入以下命令。

bp main
g

然后加载应用程序,并在输入 函数时停止。 当然, (可以使用任何入口点,而不仅仅是 main.)

如果应用程序引发异常,它将中断到调试器中。 此时提供源信息。 但是,如果使用 CTRL+CCtrl+BREAK 或调试|中断命令,调试器会创建新的线程,因此看不到源代码。

到达源文件的线程后,可以使用调试器命令窗口执行源调试命令。 如果使用 WinDbg,将显示 “源”窗口 。 如果已在“文件”菜单上单击“打开源文件”打开了源窗口,则 WinDbg 通常会为源创建新窗口。 可以在不影响调试过程的情况下关闭上一个窗口。

WinDbg GUI 中的源调试

如果使用 WinDbg,则程序计数器在调试器具有源信息的代码中后,就会立即显示一个源窗口。

WinDbg 显示你或 WinDbg 打开的每个源文件的一个源窗口。 有关此窗口的文本属性的详细信息,请参阅源Windows

然后,可以单步执行应用程序或执行到断点或游标。 有关单步执行和跟踪命令的详细信息,请参阅 控制目标

如果处于源模式,则当单步执行应用程序时,相应的“源”窗口将移动到前台。 由于应用程序执行期间还调用了 Microsoft Windows例程,因此当发生此类调用时,调试器可能会将反汇编窗口移动到前台 (,因为调试器无法访问这些函数的源) 。 当程序计数器返回到已知源文件时,相应的“源”窗口将变为活动状态。

在应用程序中移动时,WinDbg 会突出显示源窗口中的位置和反汇编窗口。 设置断点的行也突出显示。 源代码根据语言分析进行着色。 如果已选择“源”窗口,则可以将鼠标悬停在带有鼠标的符号上来评估它。 有关这些功能以及如何控制这些功能的详细信息,请参阅源Windows

若要在 WinDbg 中激活源模式,请使用 l+t 命令,在调试菜单上单击源模式,或在工具栏上的按钮上单击源模式 (screen shot of the source mode on button.) 。

当源模式处于活动状态时, ASM 指示器在状态栏上显示为不可用。

在源模式下逐步执行函数时,可以查看或更改任何局部变量的值。 有关详细信息,请参阅 读取和写入内存

调试器命令窗口中的源调试

如果使用 CDB,则没有单独的源窗口。 但是,在逐步浏览源时,仍可以查看进度。

在 CDB 中执行源调试之前,必须通过发出 .lines (切换源行支持) 命令,或通过 使用 -lines 命令行选项启动调试器来加载源行符号。

如果执行 l+t 命令,则一次执行所有程序单步执行一个源行。 使用 l-t 一次执行一个程序集指令。 如果使用 WinDbg,此命令的效果与在“调试”菜单上选择或清除源模式的效果相同,也可以使用工具栏按钮。

l+s 命令在提示符处显示当前源行和行号。 如果只想查看行号,请改用 l+l

如果使用 l+ol+s,则在单步执行程序时仅显示源行。 程序计数器、反汇编代码和注册信息被隐藏。 这种显示使你能够快速单步执行代码并查看源。

可以使用 lsp (“设置源行数”) 命令指定在单步执行应用程序时显示多少个源行。

以下命令序列是逐步执行源文件的有效方法。

.lines        enable source line information
bp main       set initial breakpoint
l+t           stepping will be done by source line
l+s           source lines will be displayed at prompt
g             run program until "main" is entered
pr            execute one source line, and toggle register display off
p             execute one source line 

由于 ENTER 重复最后一个命令,因此现在可以使用 ENTER 键逐步执行应用程序。 每个步骤都会导致源行、内存偏移量和程序集代码出现。

有关如何解释反汇编显示的详细信息,请参阅 程序集模式下的调试

显示程序集代码时,正在访问的任何内存位置将显示在行的右端。 可以使用 d* (显示内存) 和 e* (输入值) 命令查看或更改这些位置中的值。

如果必须查看每个程序集指令以确定偏移量或内存信息,请使用 l-t 逐步执行程序集指令,而不是源行。 仍可显示源行信息。 每个源行对应于一个或多个程序集指令。

所有这些命令在 WinDbg 和 CDB 中都可用。 可以使用命令从 WinDbg 的 调试器命令窗口 而不是从源窗口查看源行信息。

源行和偏移量

还可以使用表达式计算器来确定对应于特定源行的偏移量,从而执行源调试。

以下命令显示内存偏移量。

? `[[module!]filename][:linenumber]` 

如果省略 文件名,调试器将搜索对应于当前程序计数器的源文件。

除非先添加 0x,否则调试器将布劳姆伯读为十进制数,而不考虑当前的默认弧度。 如果省略 了 linenumber,表达式的计算结果为对应于源文件的可执行文件的初始地址。

仅当 .lines 命令或 -line 命令行选项已加载源行符号时,CDB 才会理解此语法。

此方法非常多才多艺,因为无论程序计数器指向何处,都可以使用它。 例如,通过此方法,可以使用以下命令提前设置断点。

bp `source.c:31` 

有关详细信息,请参阅 源行语法 和使用 断点

源模式下的单步执行和跟踪

在源模式下调试时,单个源行上可以有多个函数调用。 不能使用 pt 命令分隔这些函数调用。

例如,在以下命令中, t 命令会同时执行 GetTickCountprintf,而 p 命令将执行这两个函数调用。

printf( "%x\n", GetTickCount() );

如果要在跟踪到其他调用时单步执行某些调用,请使用 .step_filter (设置步骤筛选器) 来指示要单步执行哪些调用。

可以使用 _step_filter 筛选出框架函数 (,例如,Microsoft Foundation Classes (MFC) 或 Active Template Library (ATL) 调用) 。