断点是开发人员的工具箱中最重要的调试技术之一。 若要暂停调试程序执行所需的位置设置断点。 例如,你可能想要查看代码变量的状态或查看调用堆栈的某些断点。
命名空间或类声明或方法签名,无法设置断点。
断点显示为左边距中的一个红点。
断点符号显示黄色箭头。
如何:使用调用堆栈窗口。
-
您可以单击它,请按F9,或使用调试 > 切换断点删除或重新插入。
-
若要重新启用断点,请将鼠标悬停或右键单击它,然后选择启用断点。
-
设置条件和操作、 添加和编辑标签,或将断点导出,右键单击该和选择合适的命令,或将鼠标悬停其上,然后选择设置图标。
若要中断的指令或调用函数返回到的行处,可以设置断点调用堆栈窗口。
在调用堆栈窗口中设置断点:
-
选择调试 > Windows > 调用堆栈,或按Ctrl + Alt+C。
-
在中调用堆栈窗口中,右键单击调用函数,然后选择断点 > 插入断点,或按F9.
调用堆栈的左边距中的函数调用名称旁边会显示一个断点符号。
调用堆栈断点显示在断点窗口具有对应于在函数中的下一步可执行指令的内存位置的地址。
调试器在指令处中断。
-
选择调试 > Windows > 反汇编,或按Alt + 8。
-
此外可以选择它,然后按F9,或右键单击并选择断点 > 插入断点。
当调用函数,可以中断执行。
若要设置函数断点:
-
选择调试 > 新断点 > 函数断点,或按Alt +F9 > Ctrl+B。
您还可以选择新建 > 函数断点中断点窗口。
-
在中新函数断点对话框中,输入中的函数名称函数名称框。
若要缩小范围的函数规范:
-
使用完全限定的函数名称。
示例:
Namespace1.ClassX.MethodA() -
添加重载函数的参数类型。
示例:
MethodA(int, string) -
使用 ! 符号指定模块。
示例:
App1.dll!MethodA -
在本机中使用上下文运算符C++。
{function, , [module]} [+<line offset from start of method>]
-
-
在中语言下拉列表中,选择该函数的语言。
-
选择 确定。查看编辑器,所有 Draw() 方法处都以自动插入了断点。
为特定对象的属性发生更改时,数据断点中断执行。
若要设置数据断点
-
在.NET Core 项目中,开始调试,并等待,直到到达一个断点。
-
在自动,监视,或局部变量窗口中,右键单击一个属性,然后选择值更改时中断的上下文菜单中。
在.NET Core 中的数据断点不适用于:
- 不是可扩展的工具提示中,局部变量,自动或监视窗口属性
- 静态变量
- 使用 DebuggerTypeProxy 特性类
- 在结构内的字段
此集中的位置是在大型解决方案中,或对于复杂断点非常关键的调试方案尤其有用。
您还可以设置条件和操作,或添加新的函数或数据断点。
若要打开断点窗口中,选择调试 > Windows > 断点,或按Alt+F9或Ctrl+Alt+B。
选择一个列标题以对断点列表,可按该列进行排序。
断点标签
可以使用标签进行排序和筛选列表中的断点断点窗口。
添加新标签或选择一个现有证书,然后选择确定。
可以选择要通过选择显示的列显示列工具栏中。
调试器中的表达式。
若要设置断点条件:
-
或悬停在断点符号,选择设置图标,并选择条件中断点设置窗口。
您还可以在设置条件断点窗口中的右键单击断点并选择设置,然后选择条件。
-
在下拉列表中,选择条件表达式,命中计数,或筛选器,并相应地设置值。
-
或者,从断点窗口中,选择确定关闭对话框。
条件表达式
选择如此时,满足表达式时中断或发生更改时表达式的值已更改时中断。
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时才会跳过断点。
不同编程语言的“更改时”字段的行为不同 :
对于本机代码,调试器不会考虑更改,因此不会命中第一次计算断点条件的第一次计算。
对于托管代码,调试器命中断点后第一次计算发生更改时处于选中状态。
在条件表达式中使用对象 Id (C#和F#仅)
对象 ID 由公共语言运行时 (CLR) 调试服务生成并与该对象关联。
创建对象 ID:
1、设置断点在代码中的某个位置后创建对象。
2、开始调试,并在断点处暂停执行,选择调试 > Windows > 局部变量或Alt+ 4以打开局部变量窗口。
查找特定对象实例在局部变量窗口中,右键单击它,然后选择创建对象 ID。
这就是对象 ID。
展开名称,看到 $1 与 tri 对象完全相同
以同样的方式给 rec、cir、shapes 对象分别创建对象ID,分别对应 $2 $3 $4
右键单击该断点并选择“条件” 。
例如,如果变量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行的断点。
筛选器
可以将断点限制为仅在指定设备上或在指定进程和线程中触发。
下条件中断点设置窗口中,选择筛选器,然后输入一个或多个以下表达式:
- ProcessId = value
- ThreadId = value
可以使用 & (AND)、 || (OR)、 ! (NOT) 和括号合并子句。
提醒:断点条件 模式下进行调试,不能按F10,只能按F5进行调试才能看到实际效果。
跟踪点的作用像这种编程语言中的一个临时跟踪语句。
若要设置跟踪点:
-
或者,在断点设置窗口中,悬停在所需断点,选择设置图标,,然后选择操作。
-
C++ ) 的值。
此外可以在消息中使用以下特殊关键字:
- $ADDRESS -当前指令
- $CALLER -调用函数名
- $CALLSTACK -调用堆栈
- $FUNCTION -当前函数名
- $PID -进程 id
- $PNAME -进程名称
- $TID -线程 id
- $TNAME -线程名称
- $TICK -选中计数 (从 Windows
GetTickCount)
-
若要打印在跟踪点的消息和中断执行,请清除该复选框。
跟踪点显示为红色方块中的源代码的左边距和断点windows。
按下F5,运行结束后,查看【输出】窗口
若要确定的不同,断点上悬停并查看是否存在一条警告。
以下两个部分介绍重要警告以及如何解决这些问题。
“尚未为此文档加载任何符号”
转到模块窗口 (调试 > Windows > 模块) 并检查是否为你的模块加载。
-
如果加载你的模块,则检查符号状态列,以查看是否已加载符号。
- 指定符号 (.pdb) 和源文件。
-
以下是几个可能的原因:
- 如果最近添加的源文件,确认正在加载的模块的最新版本。
- 确认你正在使用完整 PDB 和不去除的 PDB。
- 删除文件,并执行干净的生成的模块来尝试解决此问题。
-
如果你的模块未加载,请检查以下内容来查找原因:
- 确认您正在调试的正确过程。
- 如果想要调试 C# 代码,例如,确认是否为适当类型的.NET Framework 配置您的调试器 (例如,托管 (v4*) 与托管 (v2*/v3*) 与托管 (CoreCLR))。
如果生成系统认为该项目已经是最新但没有,可以强制项目系统在重新生成通过再次保存源文件或通过清除项目的生成输出生成前。
调试没有匹配的源代码可以令人混淆的潜在顾客调试体验,因此请确保这是你想要继续操作。
若要禁用这些安全检查,请执行以下操作:
- 单击超链接,以允许修改的断点位置,然后检查允许源代码与原始不同。
- 请务必重新启用此选项,在完成时调试。
本部分提供信息以对问题进行故障排除时调试器未显示任何警告 – 断点是一个实心的红色圆时主动进行调试,但未命中断点。
下面是要检查的几个事项:
- 如果在多个进程或多台计算机运行你的代码,请确保你正在调试的正确的进程或计算机。
- 若要测试你的代码运行,将调用添加到
System.Diagnostics.Debugger.Break(C#/VB) 或__debugbreak(C++) 到在您尝试设置了断点,然后重新生成你的项目的代码行。 Debugger.Break如何工作的上一个检查中所述的测试,测试以及此问题。