vc断点知识

来源:互联网 发布:吉林省中小学网络研修 编辑:程序博客网 时间:2024/05/21 22:46

1.数据断点

注意,这个技巧仅对C++程序调试有效(或者说native程序),而且你只能在中断模式下才能设置数据断点,另外你还只能在本机设置数据断点。

上一节的例子里,我们提到了,有的时候一个全局变量被修改了以后,你可能都找不到它是什么时候被修改的,于是夜已深,人已寐,你还在辛苦地调试到底是哪个鬼地方把这个变量的值修改了。F11, F10,……,SHIFT + F11,……,F5,靠,调过了,重来,F11,F10,……

这种情况下,数据断点就很有用了,Visual Studio允许你在变量被修改的时候,中断程序的执行,是不是很酷?

默认情况下,你是找不到数据断点这个菜单的,需要执行下面的步骤把它拉出来:

打开你要调试的项目。 点击Visual Studio菜单栏里面的“工具(Tools)”—“自定义(Customize…)”。然后在“自定义(Customize…)”窗口中选择“命令(Commands)”页签里面的“种类(Categories)”列表框里的“调试(Debug)”,找到“新数据断点(New Data Breakpoint)”,将它拖到菜单栏里面相应的位置。

然后打开或者创建一个C++项目,我们以下面的源代码为例子:

#include "stdafx.h"
int g_Variable = 0;
int _tmain(int argc, _TCHAR* argv[])
{
       printf("Before modifying data breakpoints"n");
       g_Variable = 1;
       printf("After modifying data breakpoints"n");
       return 0;
}

我们现在要Visual Studio在更改g_Variable的时候中断程序的执行。

1、单击F11,这样程序就会在_tmain函数里面中断了,我们也就有机会设置数据断点了。

2、点击菜单里面的“新数据断点(New Data Breakpoint)”。注意,数据断点是通过监视内存地址某一段区域更改来实现的,因此你必须提供一个内存地址(或者说就是指针吧),这里g_Variable是一个整形变量,因此你需要使用“&g_Variable”的形式来创建一个数据断点,因为整形的 大小是4个字节,因此数据断点监视的区域是4个字节,如下图所示:

3、继续程序的执行,这时会弹出一个对话框,告诉你有一个内存地址的内容发生了变化(说明我们的数据断点生效了),这时代码行指向的是数据被修改的下一行代码,为什么会是下一行代码,下一篇文章会讲到:



二、条件中断

设置条件断点非常容易。在特定的行上,按F9设置断点。

然后右击断点–编辑窗口左侧的红点,在上下文菜单上选择“Condition…”。


这时弹出一个对话框供你设置激活该断点所需的条件。比如:我们希望只有当局部变量paginatedDinners的尺寸小于10时,调试才中断。我们可以写出如下的表达式:


现在我再运行这个程序,实现搜索,只有返回值小于10时,程序运行才会被中断。对于大于10的值,该断点将被跳过。

三、记录到达断点次数

有时你希望,只有当第N次满足条件的运行到达断点时,才中断程序运行。例如:当第五次返回少于10份晚餐的查询结果时,中断程序运行。
可以通过右击断点,然后在弹出菜单上选择“Hit count…”菜单命令实现。

这时系统弹出一个对话框,它允许你指定:(1)当满足条件,而且进入断点的累计次数等于N时,断点命中一次。(2)当满足条件,而且进入断点的累计次数是N的倍数时,断点命中一次。(3)当满足条件,而且进入断点的累计次数大于N时,每次命中断点。

四、机器/线程/进程过滤

设置如下:右击断点;在弹出菜单上选择“Filter…”菜单命令;然后指定命中断点的特定条件:在指定的机器上、或指定的进程中、或指定的线程中。

跟踪点—进入断点时的自定义操作

许多人不知道“跟踪点(TrackPoints)”这个调试功能。“跟踪点“是种特殊的断点,当它被命中时,它会触发一系列自定义操作。如果你想观察程序的行为,而又不想中断调试的时候,这个功能尤其有用。

我将用一个简单的控制台程序来演示如何使用“跟踪点”。如下是Fibonacci数列的一个递归实现:

以上程序中,我们使用Console.WriteLine() 输出针对特定输入值生成的最终斐波那契数列。如果希望在调试器里观察操作中每一次递归运算后的数列而又不实际中断程序运行,该怎么办呢?“跟踪点”可以轻松实现。

设置跟踪点

你可以在特定的行上,按F9加跟踪点。然后
右击断点,在上下文菜单中选择“When Hit…”:

在弹出对话框上,你可以设置命中该断点时,所触发的事件。

在上面例子中,我们设定一旦命中断点时就打印追踪信息。注意,我们已经把局部变量“x”的值,作为追踪信息的一部分输出。局部变量可以通过{变量名}语法输出。你还可以利用系统内置的命令($CALLER, $CALLSTACK, $FUNCTION等等),在追踪信息中输出常用的调试值。

在上例中,我们同时选中了底端的“continue execution“选项,这说明我们不希望程序中断调试状态,而是继续运行。唯一的不同是:每次断点条件满足时,我们的自定义追踪信息都将被输出。

现在当我们运行程序时,会发现自定义追踪信息自动显示在Visual Studio的“输出“窗口里。这让我们很容易看到程序的递归调用过程:

你也可以选择往应用程序中添加一个自定义追踪信息的监听器。这时追踪点的输出信息将通过它输出,而不是Visual Studio的“输出“窗口。

五、跟踪点—运行自定义的宏

当命中跟踪点时,能否自动输出所有的局部变量?

Visual Studio中并没有这样的内置功能,但我们可以写一个自定义宏来实现,然后在命中跟踪点时调用该宏。这个的实现需要先打开Visual Studio的宏编辑器(工具->宏->宏IDE菜单命令),然后在项目资源管理器的MyMacros节点下选择一个模块或创建新模块(如:加个名为“UsefulThings”的模块),再把下面的VB宏代码贴到模块中并保存。
Sub DumpLocals()
Dim outputWindow As EnvDTE.OutputWindow
outputWindow = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput).Object

Dim currentStackFrame As EnvDTE.StackFrame
currentStackFrame = DTE.Debugger.CurrentStackFrame

outputWindow.ActivePane.OutputString(“*Dumping Local Variables*” + vbCrLf)
For Each exp As EnvDTE.Expression In currentStackFrame.Locals
outputWindow.ActivePane.OutputString(exp.Name + ” = ” + exp.Value.ToString() + vbCrLf)
Next
End Sub
上述宏代码将循环当前的堆栈,把所有的局部变量输出到“输出”窗口。

使用自定义的“DumpLocals”宏

然后,我们可以在如下的一个简单程序中使用刚定制的“DumpLocals”宏了:

上述代码中,我们用F9在“Add”方法的返回值处加了个断点,然后右击断点,在弹出菜单上选择“When hit”。

将显示如下对话框。和之前不一样, 我们不选“Print a message”选项,也不手工设定需要输出的变量;而是选择“Run a marco”复选框,并指定到我们上面创建的UsefulThings.DumpLocals宏上:

为了使程序能在命中跟踪点后仍继续运行,我们将继续选中“continue execution”复选框。

运行程序

现在按F5运行程序,当“Add”方法被调用时,我们会在Visual Studio的“输出”窗口中看到如下结果。注意命中跟踪点时,宏会自动列出每个局部变量的名称和值:




0 0
原创粉丝点击