断点,可以说是 Debug 过程中最常用的功能。
但是大家最熟悉最经常使用的可能就是普通的断点。其实,关于断点,Visual Studio 有很多的高级功能,有些简直就是调试利器啊。
本次教程将介绍 Visual Studio 关于断点的更多高级玩法。
为了保证内容完整性,还是要说下普通断点。
设置普通断点的方法很简单,就是在代码行的左边栏灰色区域点击或者把光标放在某代码行,按下 F9。
如上图所示,此时左边栏出现的红色圆点就代表了一个断点。
按下 F5, Debugger 就会在此处停下来。
不像是普通的断点,程序每次执行都会停下来。条件断点的意义是,只有在条件被满足时,Debugger 才会在此处停下来。
设置条件断点一般的方法是在红点处右键选择条件或者把光标放在红点处,等待齿轮图标出现并点击。
条件断点设置窗口如下。
总共有三种类型的条件断点:
条件表达式 (Conditional Expression)
命中次数 (Hit Count)
筛选器 (Filter)
条件表达式
条件表达式也有两种类型:
为 ture (Is ture)
如下图示,此处设置的条件为: 当 testInt == 4 is ture 时命中断点。
更改时 (When changed)
如下图示,此处设置的条件为: 当 testInt 被更改的时候命中断点。
命中次数
命中次数在 Debug 循环语句时非常有用。
比如你怀疑程序出错点发生在 N 次循环之后或者某些次循环,那么可以设置循环语句内的命中次数,让它在某些次或者某次循环停下来,而不是每次都停下来。
如下图,设置的条件为:让它每隔一次循环断下来。
筛选器
筛选器是用来限制断点命中时所在的设备、进程和线程。
比如,在一个多线程的程序中,你不必手动 GetThreadId,可以通过筛选器,设置让它只在某线程中执行到此处时停下来。
筛选器表达式用法为:
MachineName = "name"
ProcessId = value
ProcessName = "name"
ThreadId = value
ThreadName = "name"
多个表达式之间可以使用运算符 & (AND), || (OR), ! (NOT) 连接 。
在断点设置窗口,除了条件,我们还可以看到操作 (Action)选项框。
操作 (Action) 的意义是设置追踪点 (Tracepoint)。
Tracepoint 相当于是一种临时的有 Trace 功能的断点,它会把消息打印到 Output 窗口。
勾选后面的继续执行 (Continue Execution),代表 Tracepoint 命中时,Debugger 不会停下来,否则将会在此处停下来。两种情况下,消息都会打印出来。
可以使用下面的关键字作为消息。
在 Debug 菜单下,点击新建断点,可以新建两种类型的断点:函数断点 (Function Breakpoint)和数据断点(Data Breakpoint)。
函数断点是通过函数名设置断点,当程序执行到该函数的时候断点断下来。
紧接上面,这里讲下数据断点。
数据断点的意义是,让程序在当某处地址指定字节发生改变的时候中断下来。它只有在 Break Mode 下才可以设置。
地址栏可以用具体的内存地址,也可以用表达式来代表内存地址。例如,可以使用 &avar,让程序在当变量 avar 内容发生改变的时候中断下来。
也许你不知道,是可以在 Call Stack 窗口设置断点的。
当你在查看函数的调用关系的时候,想在这一些列的函数中快速设置断点,那么其实很简单:在 Call Stack 窗口,点击想要设置断点的函数所在的行,按下 F9 即可。
还可以在 Disassembly 窗口设置断点。但前提必须是 Break Mode 下。
反汇编窗口设置断点的方式跟在源代码中设置断点的方式相同,只要在代码左边栏边缘处点击一下,红色圆点就出现了。
我们前面所设置的所有断点都会出现在断点窗口 (Breakpoints Windows)。
在这里,可以对所有的断点进行管理,比如批量启用、禁用、删除等,还可以在程序运行过程中,查看断点的命中状态。
当你的工程非常大,Debug 时设置了很多的断点的时候,它会非常有用。