Visual Studio调试器指南---断点和跟踪点

断点告诉调试器应用程序应该在某个点中断或暂停执行。当中断发生时,程序和调试器被称为处于中断模式。跟踪点是Visual Studio中的一个新调试器功能。跟踪点是具有与其关联的自定义操作的断点。当命中跟踪点时,调试器将执行指定的跟踪点操作,而不是中断程序执行。跟踪点的一个常见用途是在程序到达某个点时打印消息。您可以将跟踪点用于许多与使用跟踪相同的目的,但无需修改代码。另一个区别是,跟踪点只在调试器下运行时工作。

断点概述

断点标志符号

源窗口和反汇编窗口通过在左边距中显示名为glyph的符号来显示断点位置。下表描述了这些标志符号。如果将鼠标放在断点图示符上,则会出现一个断点提示,其中包含更多信息。此信息对于错误和警告断点特别有用。

Glyph

Description

Debug Glyph 1

正常断点。实心标志符号表示断点已启用。空心标志符号表示它已被禁用。

Debug Glyph 2

高级断点。激活/禁用。符号+表示断点至少附加了一个高级功能(如条件、命中计数或筛选器)。

Debug Glyph 3

映射断点。激活/禁用。断点在ASP/ASP.NET代码中设置并映射到相应HTML页面中的断点,或者在服务器端脚本文件中设置并映射到相应的客户端脚本文件。

Debug Glyph 4

追踪点。激活/禁用。达到此点将执行指定的操作,但不会中断程序执行。

Debug Glyph 5

高级跟踪点。激活/禁用。符号+表示跟踪点至少附加了一个高级功能(如条件、命中计数或筛选器)。

Debug Glyph 6

映射跟踪点。激活/禁用。跟踪点在ASP/ASP.NET代码中设置,并映射到相应HTML页面中的跟踪点。

Debug Glyph 7

断点或跟踪点错误。X表示由于错误条件,无法设置断点或跟踪点。

Debug Glyph 8

断点或跟踪点警告。感叹号表示由于临时条件,无法设置断点或跟踪点。通常,这意味着断点或跟踪点位置的代码尚未加载。如果附加到进程并且未加载该进程的符号,则也可以看到。加载代码或符号时,将启用断点并更改图示符

基本断点

最基本的断点是在源代码行或函数上设置的断点。注意:如果一个源文件中有超过64000行代码,则不会命中64000行之后的行上的断点。

一行上有多个断点

有时,一行代码包含多个可执行语句。在这种情况下,可以在行上设置多个断点。包含当前选定断点的代码语句周围将出现一个框。此框可用于区分同一行代码上的多个断点。可以在“断点”窗口中选择断点,也可以单击“源”窗口中包含断点的语句。

高级断点

如果您有VisualC++或VisualStudio,任何版本,您可以设置更高级的断点,创建具有高级特性的断点,并以更强大的方式使用断点。

内存地址和内存更改上的断点

可以在内存地址上设置断点,也就是地址断点。在C/C++中,可以设置一个在内存更改时命中的断点,也就是数据断点(仅限本机)。

筛选、命中计数和条件

过滤器、命中计数和条件是可以附加到任何类型断点(包括跟踪点)的高级功能。

  • 筛选器导致在指定的计算机、进程和线程上设置断点。在调试运行在多个处理器上的应用程序时,筛选器非常有用。
  • 命中计数跟踪断点被命中的次数。默认情况下,断点在每次被命中时都会中断执行。您可以更改此行为,以便只有当命中计数等于或超过指定值或命中计数是给定值的倍数时,断点才会断开。指定的命中计数仅为调试会话保留。
  • 条件是一个表达式,计算该表达式以确定断点是否将断开。

断点限制

在调试混合模式、本机和托管代码时,请避免在系统组件上设置断点。在混合模式调试期间在系统组件上设置断点可能会导致公共语言运行库中断,调试器停止响应。除非您单步执行调用,否则调试器不会自动附加到XML Web服务。这意味着在XML Web服务中设置的任何断点都不会被命中,除非您进入调用。如果尝试使用“开始调试”或“继续”来运行断点,而不是使用“单步执行”,则不会命中断点。

设置简单断点

Visual Studio调试器提供了许多设置断点的方法。下面提供了两种设置简单断点的快速方法。

  • 在快捷菜单上设置简单断点
    在源窗口中,右键单击要设置断点的可执行代码行。在快捷菜单上,单击“断点”,然后单击“插入断点”。
  • 在“调试”菜单上设置简单断点
    在源窗口中,单击要设置断点的可执行代码行。在“调试”菜单上,单击“切换断点”。

设置地址断点

可以在“反汇编”窗口中的内存地址处设置断点。设置断点后,可以在“断点”窗口中编辑地址断点。先转到汇编窗口,然后进行下面的操作:

在“反汇编”窗口中,单击一行代码,然后单击“调试”菜单上的“切换断点”。

-或者-
右键单击一行代码,然后选择“插入断点”。

设置函数断点

可以在函数的开头或函数中的指定位置设置断点。对于脚本,只能在函数的开头设置断点。

  • 插入函数断点
    (可选)在源窗口中,单击函数的名称。这会将函数的名称插入到“新建断点”对话框中,以便您不必键入它。
    在“调试”菜单上,指向“新建断点”,然后单击“函数断点”。

    出现“新建断点”对话框。

    如果“函数”文本框不显示要设置断点的函数的名称,请在“函数”框中键入函数名称,并确保“语言”下拉列表显示该函数的正确编程语言。如果函数未重载,则只需要函数名。对于重载函数,可以指定参数以正确设置断点。键入函数名,后跟括在括号中的参数类型名。例如,对于一个名为a的C#方法,它接受一个带字符串参数和int参数,请键入a(int,string)。
    在本机C++中,可以使用上下文运算符。(仅限Visual Basic和C)如果希望Visual Studio Intellisense验证输入的函数名,请选中“使用Intellisense验证函数名”复选框。
    如果选中该复选框,并且键入的内容与重载签名不匹配,则会出现“选择断点”对话框,您可以选择要放入断点的重载。如果未选中该复选框并键入函数名,则断点将放入所有重载中。如果未选中该复选框,并且键入的签名不匹配,则不会在代码中插入断点。
    断点设置在函数的开头。如果要在函数中的其他位置设置断点,请更改“行”和“字符”框中的值。
    单击“确定”。
  • 从“断点”窗口插入函数断点

    后面的操作跟上面一样。

从调用堆栈窗口设置函数调用的断点

此功能不适用于Transact-SQL、Internet Explorer中的脚本或ASP。本主题描述如何使用调用堆栈窗口在对函数的特定调用上设置断点。断点在函数调用中的下一个可执行指令处设置。如果要在函数本身上设置断点,而不是在对函数的特定调用上设置断点。

在“调用堆栈”窗口中,在中断模式下,右键单击函数调用,然后单击快捷菜单(断点子菜单)上的“插入断点”。断点符号出现在函数调用名称旁边的左边距中。查看断点属性时,此断点显示为地址断点,其内存位置与函数中的下一个可执行指令相对应。

设置数据断点(Native Only)

当写入存储在指定内存位置的值时,数据断点中断执行。如果值是读而不是写的,则执行不会中断。数据断点在以下情况下不起作用:如果未被调试的进程写入内存位置,或者内存位置在两个或多个进程之间共享。如果在内核中更新了内存位置,则数据断点不起作用。例如,如果内存被传递给32位Windows ReadFile函数,则内存将从内核模式更新,并且调试器不会在内存写入时中断。若要设置数据断点,调试器必须仅处于中断模式。变量的地址从一个调试会话更改到下一个调试会话。因此,在每个调试会话结束时,数据断点都会被自动禁用。如果在局部变量上设置了数据断点,则在函数结束时,数据断点将保持启用状态。但是,它设置的内存地址不再具有相同的含义。因此,这种断点的结果是不可预测的。如果在局部变量上设置数据断点,最佳做法是在函数结束之前删除或禁用断点。

Visual Studio支持每个解决方案最多四个数据断点。

  1. 在“调试”菜单上,选择“新建断点”,然后单击“新建数据断点”。

    -或者-
    在“断点”窗口菜单中,单击“新建”,然后选择“新建数据断点”。
  2. 出现“新建断点”对话框。在“地址”框中,键入计算结果为内存地址的内存地址或表达式。例如,键入&avar以在变量avar的内容更改时中断。
  3. 在“字节计数”框中,键入希望调试器监视的字节数。例如,如果键入4,调试器将监视从&myFunction开始的四个字节,如果这些字节中的任何一个改变了值,调试器将中断这些字节。
  4. 单击“确定”。

删除断点

在源窗口、反汇编窗口或调用堆栈窗口中,断点显示为红色符号或标志符号。

删除一个断点

在“断点”窗口中,右键单击断点,然后单击快捷菜单上的“删除”。

-或者-
在源窗口或反汇编窗口中,单击断点图示符。

删除所有断点

在“调试”菜单中,单击“删除所有断点”。

启用或禁用断点

启用或禁用一个断点

在“源”、“反汇编”或“调用堆栈”窗口中,右键单击包含断点标志符号的行,指向“断点”,然后单击“启用断点”或“禁用断点”。

-或者-
在“断点”窗口中,选中或清除断点旁边的复选框。

启用或禁用多个断点

在“调试”菜单中,单击“启用所有断点”。

编辑断点位置

  1. 在“断点”窗口中,右键单击断点,然后单击快捷菜单上的“位置”。
    -或者-
    在“源”、“反汇编”或“调用堆栈”窗口中,右键单击包含断点图示符的行,然后在快捷菜单上单击“从断点定位”。
    在源窗口中,可能必须右键单击设置断点的确切字符。如果断点设置在源代码行内的特定字符上,则这是必需的。
  2. 对于文件断点,编辑文件以更改设置断点的文件,编辑行以更改文件中的行号,或编辑字符以更改该行上的水平位置。
    默认情况下,只有设置断点的源文件版本与可执行文件的编译源文件完全匹配时,才会命中文件断点。若要更改此默认值,请清除“一般调试选项”对话框中的“要求源文件与原始版本完全匹配”。
    -或者-
    对于地址断点,请编辑address以更改设置断点的内存位置,或编辑Language以更改调试器计算地址框中表达式的语法。
    -或者-
    对于函数断点,编辑函数更改设置断点的函数的签名,编辑行更改函数中的行号,或编辑字符更改该行上的水平位置。
    如果希望Visual Studio Intellisense检查输入的函数名的有效性,请选中“使用Intellisense验证函数名”。
    -或者-
    对于数据断点,编辑地址以更改要监视的内存位置,或编辑字节计数以更改要监视的字节数。

指定断点条件

断点条件是调试器在到达断点时计算的表达式。如果条件满足,调试器将检查如何:指定命中计数以确定是否中断(或执行另一个指定的操作)。条件可以是调试器识别的任何有效表达式。例如,在银行程序中,可以设置断点条件,例如balance<0。如果使用无效语法设置断点条件,则会立即显示警告消息。如果使用有效语法但无效语义指定断点条件,则在第一次命中断点时将显示警告消息。在这两种情况下,调试器在命中无效断点时中断执行。仅当条件有效且计算结果为false时,才会跳过断点。
  1. 在“断点”窗口中,右键单击包含断点图示符的行,然后单击快捷菜单上的“设置”。

    -或者-
    在源、反汇编或调用堆栈中,右键单击包含断点标志符号的行,然后单击快捷菜单上的“断点条件”。
  2. 在“断点条件”对话框中,在“条件”框中输入有效表达式,例如myLocalVariable>1。
  3. 如果要在满足表达式时断开,则选择为true;如果要在表达式值更改时断开,则选择已更改。

在第一次到达断点之前,调试器不会计算表达式。如果为本机代码选择“已更改”,则调试器不会将条件的第一次求值视为更改,因此不会在表达式的第一次求值时命中断点。如果为托管代码选择“已更改”,则在选择“已更改”后的第一次求值时将命中断点。

指定命中次数

命中计数跟踪断点被命中的次数。默认情况下,每次遇到断点时执行都会中断。您可以选择:

  • 始终中断(默认设置)。
  • 当命中计数等于指定值时中断。
  • 当命中数等于指定值的倍数时中断。
  • 当命中数大于或等于指定值时中断。

如果要跟踪断点被命中但从不中断执行的次数,可以将命中计数设置为非常高的值,以便从不命中断点。指定的命中计数仅为调试会话保留。调试会话结束时,命中计数重置为零。

  • 在“断点”窗口中,右键单击断点,然后单击快捷菜单上的“命中计数”。
    -或者-
    在“源”、“反汇编”或“调用堆栈”窗口中,右键单击包含断点的行,然后从快捷菜单上的“断点”子菜单中单击“命中计数”。
  • 在“命中计数”对话框中,从“断点命中时”列表中选择所需的行为。如果选择了“始终中断”以外的任何设置,则列表旁边会显示一个文本框。编辑文本框中显示的整数以设置所需的命中计数。
  • 点击OK.

指定断点筛选器

断点筛选器将断点的行为限制为指定的计算机、进程和线程。当调试分布在多个处理器上的并行应用程序时,断点筛选器可能很有用。

  1. 在“断点”窗口中,右键单击断点,然后单击快捷菜单上的“筛选”。-或者-在源、反汇编或调用堆栈中,右键单击包含断点标志符号的行,然后在快捷菜单上选择“从断点筛选”。在“断点筛选器”对话框中,使用“筛选器”框按名称和进程指定计算机,或按名称或ID号指定线程。
  2. 单击OK

指定跟踪点/断点操作

跟踪点是一种使用断点的新方法。跟踪点是具有与其关联的自定义操作的断点。当跟踪点被命中时,它会导致调试器执行指定的操作,而不是(或除此之外)中断程序执行。您可以用两种不同的方式创建跟踪点:

  • 通过添加跟踪点操作,可以将现有断点转换为跟踪点。任何类型的断点都可以转换为跟踪点。
  • 可以使用New tracepoint命令从头创建跟踪点。

从头开始创建跟踪点

在源窗口中,单击要设置跟踪点的行,然后在快捷菜单上选择“插入跟踪点”。

“命中时”对话框出现。它包含两个文本框,您可以在其中输入自定义操作:打印消息和运行宏。

此时,您可以接受预选的跟踪点设置,或按如下方式修改它们:
要创建将消息打印到输出窗口的跟踪点,请选择打印消息并在相应的文本框中输入消息文本。通过使用打印消息,可以将跟踪点用于与使用跟踪类相同的目的,但无需修改代码。
可以使用DebuggerDisplayAttribute语法包含编程信息。例如:
在函数{$FUNC}中,在线程{$TID}上
-或者-
使用的变量:{varName},函数名:{function name($FUNC)}
您可以使用“命中断点时”对话框中显示的任何关键字。此外,还可以使用对话框中未显示的其他两个关键字:$TICK插入当前CPU计时计数,而$FILEPOS插入当前文件位置。当“命中断点时”对话框打开时,“打印消息”中将显示默认消息。如果要接受此消息,请单击“确定”。要运行Visual Studio自动化模型宏,请选择“运行宏”,然后从下拉列表中选择宏。当您选择打印消息或运行宏时,“继续执行”复选框将变为活动状态。如果不希望跟踪点中断程序的执行,请选择“继续执行”。

从现有断点创建跟踪点

在“源”、“反汇编”或“调用堆栈”窗口中,右键单击断点标志符号并选择“操作”。

-或者-
在“断点”窗口中,右键单击断点图示符并选择“设置”。

对话框出现。

断点失败

如果项目中的两个或多个源文件具有相同的名称,则调试器可能无法确定断点设置在哪个文件中。如果创建的模块与要链接的调试库的组件同名,则通常会发生这种情况。要解决此问题,请输入源文件的完整路径。可以在“文件断点”对话框中更改文件路径名。在其他情况下,调试器可能找不到对应于断点的源文件,即使源文件存在。如果源文件已更改,并且源与正在调试的代码不再匹配,则会发生这种情况。如果希望Visual Studio显示与正在调试的版本不匹配的源代码,请在“选项”对话框的“常规”类别的“调试”节点中清除“仅使用与原始版本完全匹配的源代码”选项。也可以通过选中“文件断点”对话框中的“允许源代码与原始版本不同”来绑定断点。

posted on 2020-03-13 09:53  活着的虫子  阅读(3500)  评论(1编辑  收藏  举报

导航