断点是开发人员的工具箱中最重要的调试技术之一。 若要暂停调试程序执行所需的位置设置断点。 例如,你可能想要查看代码变量的状态或查看调用堆栈的某些断点。
01 在源代码中设置断点
可以在任意可执行代码行上设置断点。 例如,在以下 C# 代码,可以设置断点在变量声明for
循环中或内的任何代码for
循环。 命名空间或类声明或方法签名,无法设置断点。
若要在源代码中设置断点,请单击代码行旁边的最左侧边距中。 您还可以选择行,然后按F9,选择调试 > 切换断点,或右键单击并选择断点 > 插入断点。 断点显示为左边距中的一个红点。
调试时,执行的断点处暂停,在执行该行上的代码之前。 断点符号显示黄色箭头。
当调试器在断点处停止时,您可以查看应用程序,包括变量值和调用堆栈的当前状态。 有关调用堆栈的详细信息,请参阅如何:使用调用堆栈窗口。
02 调用堆栈窗口中设置断点
若要中断的指令或调用函数返回到的行处,可以设置断点调用堆栈窗口。
在调用堆栈窗口中设置断点:
调用堆栈断点显示在断点窗口具有对应于在函数中的下一步可执行指令的内存位置的地址。
调试器在指令处中断。
03 在反汇编窗口中设置断点
04 设置函数断点
当调用函数,可以中断执行。
若要设置函数断点:
Namespace1.ClassX.MethodA()
MethodA(int, string)
App1.dll!MethodA
{function, , [module]} [+<line offset from start of method>]
示例:{MethodA, , App1.dll}+2
05 设置数据断点 (.NET Core 3.0 或更高版本)
为特定对象的属性发生更改时,数据断点中断执行。
若要设置数据断点
在.NET Core 中的数据断点不适用于:
06 在“断点”窗口中管理断点
可以使用断点窗口来查看和管理你的解决方案中的所有断点。 此集中的位置是在大型解决方案中,或对于复杂断点非常关键的调试方案尤其有用。
在断点窗口中,您可以搜索、 排序、 筛选、 启用/禁用或删除断点。 您还可以设置条件和操作,或添加新的函数或数据断点。
若要打开断点窗口中,选择调试 > Windows > 断点,或按Alt+F9或Ctrl+Alt+B。
若要选择要在列表中显示的列断点窗口中,选择显示列。 选择一个列标题以对断点列表,可按该列进行排序。
可以使用标签进行排序和筛选列表中的断点断点窗口。
1、若要将标签添加到断点中,右键单击该断点的源代码中或断点窗口中,并选择编辑标签。 添加新标签或选择一个现有证书,然后选择确定。
2、对在断点列表进行排序断点通过选择窗口标签,条件,或其他列标题。 可以选择要通过选择显示的列显示列工具栏中。
07 断点条件
可以通过设置条件来控制在何时何处执行断点。 条件可以是调试器能够识别任何有效表达式。 有关有效表达式的详细信息,请参见调试器中的表达式。
若要设置断点条件:
当选择条件表达式,可以选择两个条件:为 true或发生更改时。 选择如此时,满足表达式时中断或发生更改时表达式的值已更改时中断。
1、示例1,设置条件表达式为 true, index == 1
按下F5,启动调试,由于第一次 index 等于0,所以37行断点没有命中,直接走到43行的正常断点处。
第一次循环结束后,index的值增加了1,等于1。进入到第二次循环时,按下F5,由于 index = 1,满足设置的表达式,所以命中了37行的断点。
第二次循环结束后,index的值增加了1,等于2。进入到第三次循环时,按下F5,由于 index = 2,不满足设置的表达式,所以没有命中37行的断点,直接走到43行的正常断点处。
2、示例2:设置条件表达式为 更改时, index
按下F5,启动调试,由于第一次 index 等于0,第一次进入循环,结束前 index的值未改变仍然为0,没有改变,所以37行断点没有命中,直接走到43行的正常断点处。
第一次循环结束后,index的值增加了1,等于1。进入到第二次循环时,按下F5,由于 index = 1,值更改了,满足设置的条件,所以命中了37行的断点。
第二次循环结束后,index的值增加了1,等于2。进入到第三次循环时,按下F5,由于 index = 2,值更改了,满足设置的条件,所以命中了37行的断点。
如果使用无效语法设置断点条件,则会显示警告消息。 如果在指定断点条件时使用的语法有效但语义无效,则在第一次命中断点将出现警告消息。 在任一情况下,调试器将中断时它会命中断点无效。 仅在条件有效且计算结果为 false
时才会跳过断点。
不同编程语言的“更改时”字段的行为不同 : 对于本机代码,调试器不会考虑更改,因此不会命中第一次计算断点条件的第一次计算。 对于托管代码,调试器命中断点后第一次计算发生更改时处于选中状态。
有些的时候,当你想要观察特定对象的行为。 例如,你可能想要找出为什么对象插入到集合一次以上。 在 C# 和 F# 中,可以创建引用类型的特定实例的对象 ID,并在断点条件下使用它们。 对象 ID 由公共语言运行时 (CLR) 调试服务生成并与该对象关联。
创建对象 ID:
1、设置断点在代码中的某个位置后创建对象。
2、开始调试,并在断点处暂停执行,选择调试 > Windows > 局部变量或Alt+ 4以打开局部变量窗口。
查找特定对象实例在局部变量窗口中,右键单击它,然后选择创建对象 ID。
应该会在“局部变量” $ 窗口中看到, $ 窗口中设置断点来中断调用函数返回到的指令或行处的执行。 这就是对象 ID。
展开名称,看到 $1 与 tri 对象完全相同
以同样的方式给 rec、cir、shapes 对象分别创建对象ID,分别对应 $2 $3 $4
3、在该对象添加到集合处, 右键单击该断点并选择“条件” 。
4、在“条件表达式”字段中使用对象 ID 。 例如,如果变量item
是要添加到集合中,选择的对象为 true并键入item == $<n > ,其中<n > 的对象 ID 号.
会在将该对象添加到集合中时中断执行。
tri 对象添加到集合处,设置条件为 tri == $1
rec 对象添加到集合处,设置条件为 rec == $2
cir 对象添加到集合处,设置条件为 rec == $3
按下F5继续运行,
代码走到61行时,断点变成黄色箭头,鼠标悬浮在黄色箭头上,提示如下,条件表达式计算结果为 true。所以命中61行的断点。
按下F5继续运行,
代码走到62行时,断点变成黄色箭头,鼠标悬浮在黄色箭头上,提示如下,条件表达式计算结果为 true。所以命中62行的断点。
按下F5继续运行,
代码走到63行时,断点变成黄色箭头,鼠标悬浮在黄色箭头上,提示如下,条件表达式计算结果为 true。所以命中63行的断点。
如果将61行的条件设置为 tri == $2。根据上述的生成的对象ID,该表达式返回false。
再次F5,运行到61行时,提示报错。因为 tri 是 Triangle 类的对象,$2 是 Rectangle 类的对象创建的ID,所以无法进行 == 运算符的比较。调试器报错。
但是按下F5,仍然可以继续运行。
如果把61行的条件表达式修改为 tri.Equals($2),再次调试时,由于该表达式返回false,所以没有命中61行的断点。直接跳到62行。
若要删除对象 ID,请右键单击中的变量局部变量窗口,然后选择删除对象 ID。
对象 ID 创建弱引用,且不会阻止对象被垃圾回收。 它们仅对当前调试会话有效。
如果你怀疑你的代码中的循环开始产生错误行为在一定数量的迭代后,可以设置一个断点以停止执行的命中数,而无需重复按该数后F5来访问该迭代。
下列条件中断点设置窗口中,选择命中计数,然后指定迭代数。 在以下示例中,断点设置为其他每次迭代命中:
F5调试,第一次 i = 0,不是 testInt 的2倍整数,所以没有命中74行的断点,直接跳到76行。
当 testInt的值为 2、4、16、22、46时,都能命中74行的断点。
可以将断点限制为仅在指定设备上或在指定进程和线程中触发。
下条件中断点设置窗口中,选择筛选器,然后输入一个或多个以下表达式:
将字符串值放在双引号内。 可以使用 &
(AND)、 ||
(OR)、 !
(NOT) 和括号合并子句。
提醒:断点条件 模式下进行调试,不能按F10,只能按F5进行调试才能看到实际效果。
08 断点操作和跟踪点
“跟踪点”是将消息打印到“输出”窗口的断点 。 跟踪点的作用像这种编程语言中的一个临时跟踪语句。
若要设置跟踪点:
GetTickCount
)跟踪点显示为红色方块中的源代码的左边距和断点windows。
按下F5,运行结束后,查看【输出】窗口
09 断点警告
断点在调试时,有两个可能的可视状态: 一个实心的红色圆和 (白色填充) 空心圆。 如果调试器能够成功在目标进程中设置断点,它将保持一个实心的红色圆。 如果断点是空心圆,禁用断点,或尝试设置断点时出现警告。 若要确定的不同,断点上悬停并查看是否存在一条警告。
以下两个部分介绍重要警告以及如何解决这些问题。
转到模块窗口 (调试 > Windows > 模块) 并检查是否为你的模块加载。
如果源文件已更改,并且源与正在调试的代码不再匹配,调试器不会设置断点在代码中默认情况下。 通常情况下,此问题发生时更改源文件,但不重新生成的源代码。 若要解决此问题,重新生成项目。 如果生成系统认为该项目已经是最新但没有,可以强制项目系统在重新生成通过再次保存源文件或通过清除项目的生成输出生成前。
在极少数情况下,你可能想要调试而无需匹配的源代码。 调试没有匹配的源代码可以令人混淆的潜在顾客调试体验,因此请确保这是你想要继续操作。
若要禁用这些安全检查,请执行以下操作:
10 断点已成功设置 (无警告),但未命中
本部分提供信息以对问题进行故障排除时调试器未显示任何警告 – 断点是一个实心的红色圆时主动进行调试,但未命中断点。
下面是要检查的几个事项:
System.Diagnostics.Debugger.Break
(C#/VB) 或__debugbreak
(C++) 到在您尝试设置了断点,然后重新生成你的项目的代码行。Debugger.Break
如何工作的上一个检查中所述的测试,测试以及此问题。11 删除了断点,但在再次启动调试时继续命中该断点
如果在调试时删除了断点,可能在下一步启动调试的时再次命中该断点。 要停止命中此断点,请确保从 “断点” 窗口删除该断点的所有实例。