原文链接地址:http://blog.csdn.net/Donjuan/article/details/4618717

函数断点

在前面的文章Visual Studio调试之避免单步跟踪调试模式里面我讲了如何设置函数断点,说实话,我个人喜欢设置函数断点,而不是在代码行里面设置断点。一般来说,函数断点在下面几种情形下有用:

1. 例如调试一个网站程序,你通过分析网站的日志发现最有可能发生错误的函数,打开调试器并将调试器附加到程序上去,设置函数断点,重新执行网站……这样做的好处是,不用到处打开源文件去找出错的源代码行,调试器会自动打开源代码,并且在函数的入口处中断(岂不是很方便?)。

2. 例如你在阅读源代码的时候,通常在读到虚函数调用的时候,因为通常这种调用都是通过基类指针调用的,而你又一时半会不知道到底有哪个继承类的Overloading函数会被调用到,函数断点可以告诉你。

3. 或者一种特殊的情形,你想读一个程序的源代码,但就是找不到入口Main函数,例如.NET程序,那么直接在Visual Studio里面按F11就能帮你找到入口函数—这是函数断点的一个特殊情形。

4. 比如你在调试Web Service函数,设置函数断点也是一个快捷的调试方法,这个技巧跟技巧1类似。

当然,可能有些读者没有办法成功设置函数断点,如果设置函数断点失败,请阅读我的文章“不能设置断点的检查步骤”。如果里面有一些名词术语(术语请参看文章:调试术语)不知道或者不知道如何设置的话,呃,我会另写一篇文章讲解。

断点编程

有的时候你可能会碰到这种情况,触发一个断点以后,你发现需要修改一些值,才能使程序继续正确执行下去。例如我以前在中文版本的操作系统上,使用sscli里面(调试版)的csc.exe编译器编译一些包含语法错误或者语法警告的C#源文件的时候,csc.exe总是会莫名其妙地报告内部严重错误,然后就崩溃了。我将调试器附加上去以后,发现是一个ASSERT错误,ASSERT(lcid == 0x409),表示sscli里面的csc.exe总是默认自己在英文操作系统(或者说英文环境)里面运行。而且这一条语句会被执行很多次,手工修改lcid的值的确有点麻烦。然后我找源代码找来找去都没有找到csc.exe在哪个地方获取到这个lcid值(当然我最后找到了,下一个技巧将告诉你我是怎么找到的),然而我又不想重启系统(呃……也许我就是那种宁愿花1个钟头去找节省花费5分钟重启系统的方法的那种人……)。

这个时候如果调试器可以自动帮你重置lcid的值该有多好?幸运的是,Visual Studio提供了方法让你完成这样的工作。下面是一个简化的代码,因为我一时半会找不到sscli了:

int lcid = System.Globalization.CultureInfo.CurrentUICulture.LCID;

Console.WriteLine("lcid = {0}", lcid);

上面的代码在正常情况下,应该返回当前操作系统语言的lcid值,例如英文就是1033,中文的,呃……我忘记了。假设我们现在希望做的是,每当lcid的值为1033的时候,就自动更正为0。我们需要:

1. 在Console.WriteLine这一行上设置一个条件断点,条件断点的设置请参看Visual Studio调试之断点进阶篇

2. 点击Visual Studio菜单栏里面的“工具(Tools)”—“宏(Macro)”—“宏资源管理器(Macro Explorer)”。然后创建一个新的宏:

Imports System

Imports EnvDTE

Imports EnvDTE80

Imports EnvDTE90

Imports System.Diagnostics

Imports Microsoft.VisualBasic

Imports Microsoft.VisualBasic.ControlChars

Public Module Module1

Sub ChangeExpression()

DTE.Debugger.ExecuteStatement("lcid = 0;")

End Sub

End Module

上面DTE.Debugger.ExecuteStatement的作用,你可以理解成在立即窗口中执行lcid = 0;这条语句。

3. 右键点击刚才设置好的断点,在菜单里面选择“When Hit …”,这一次在“When Breakpoint is Hit”窗口中勾选“Run a macro:(执行一个宏)”,然后在下拉框里面选择刚才你创建的宏的名称。如果你是第一次创建宏,名称应该是:Macros.MyMacros.Module1.ChangeExpression。

4. 勾选“继续执行(Continue execution)”,因为我们并不想让程序中断下来。

5. 点击确定以后,执行程序看一看结果,lcid是不是已经被自动改成0了?

数据断点

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

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

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

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

1. 打开你要调试的项目。

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

呃,为什么数据断点只能在C++/C程序中才能设置?是因为托管代码有垃圾回收。而数据断点的执行原理应该是Windows内存管理里面的Guard Pages概念和VirtualProtectEx函数的实现。这个概念可以自己去查MSDN的内存管理方面的文档。

Visual Studio调试之断点技巧篇的更多相关文章

  1. Visual Studio调试之断点技巧篇补遗

    原文链接地址:http://blog.csdn.net/Donjuan/article/details/4649372 讲完Visual Studio调试之断点技巧篇以后,翻翻以前看得一些资料和自己写 ...

  2. Visual Studio调试之断点进阶篇

    Visual Studio调试之断点进阶篇 在上一篇文章Visual Studio调试之断点基础篇里面介绍了什么是断点,INT 是Intel系列CPU的一个指令,可以让程序产生一个中断或者异常.程序中 ...

  3. Visual Studio调试之断点基础篇

    Visual Studio调试之断点基础篇 我曾经问过很多人,你一般是怎么调试你的程序的? F9, F5, F11, F…… 有很多书和文章都是介绍怎么使用Visual Studio编写WinForm ...

  4. VISUAL STUDIO 调试

    调试术语 Visual Studio调试之断点基础篇 Visual Studio调试之断点进阶篇 不能设置断点的检查步骤 Visual Studio调试之断点技巧篇 Visual Studio调试之断 ...

  5. Visual Studio调试之避免单步跟踪调试模式

    Visual Studio调试之避免单步跟踪调试模式 写完Visual Studio调试之断点进阶篇之后,想分享一下我常用的一些调试技巧,后面发现写之前,一些背景知识需要介绍一下. 下面是几篇今年2月 ...

  6. Visual Studio调试之符号文件

    原文链接地址:http://www.cnblogs.com/killmyday/archive/2009/10/14/1582882.html 前面在不能设置断点的检查步骤和Visual Studio ...

  7. [转]Visual Studio调试之符号文件

    http://www.cnblogs.com/killmyday/archive/2009/10/14/1582882.html 前面在不能设置断点的检查步骤和Visual Studio调试之断点进阶 ...

  8. 12个Visual Studio调试效率技巧

    在这篇文章中,我们假定读者了解VS基本的调试知识,如: F5 开始使用调试器运行程序 F9 在当前行设置断点 F10 运行到下一个断点处 F5 从被调试的已停止程序恢复执行 F11 步进到函数内(如果 ...

  9. Visual Studio 调试技巧[Command Window & Immediate Window ](Tips)

    Visual Studio 调试技巧[Command Window & Immediate Window ](Tips) 1. immediate window 定义的一些 alias (// ...

随机推荐

  1. Linux之MariaDB

    MariaDB数据库的起源 MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜 ...

  2. Hadoop(7)-HDFS客户端的API操作

    1 客户端环境准备 根据自己电脑的操作系统拷贝对应的编译后的hadoop jar包到非中文路径 配置HADOOP_HOME的环境变量,并且在path中配置hadoop的bin 重启电脑 2. Hdfs ...

  3. CentOS下禁止防火墙

    CentOS下禁止防火墙 1.使用如下命令安装iptables-services. yum install -y iptables-services 2.关闭防火墙. service iptables ...

  4. hive的load命令

    Hive Load语句不会在加载数据的时候做任何转换工作,而是纯粹的把数据文件复制/移动到Hive表对应的地址. 语法 LOAD DATA [LOCAL] INPATH 'filepath' [OVE ...

  5. Kubernetes-深入分析集群安全机制(3.6)

    集群的安全性主要考虑以下几个方面: 容器与所在宿主机的隔离: 限制容器给基础设施及其他容器带来消极影响的能力: 最小权限原则--合理限制所有组件的权限,确保组件只执行它被授权的行为,通过限制单个组件的 ...

  6. 3122 奶牛代理商 VIII(状压dp)

    3122 奶牛代理商 VIII  时间限制: 3 s  空间限制: 256000 KB  题目等级 : 大师 Master     题目描述 Description 小徐是USACO中国区的奶牛代理商 ...

  7. 前端学习webpack

    ### 模块化- 为了保证代码充分解耦,一个大的项目拆分成互相依赖的一个一个的小的模块,最后再通过简单的方式合并在一起- 每一个js文件都可以看成一个单独的模块在node这边(服务器端),提出Comm ...

  8. vs调试代码的时候断点无法命中

    https://blog.csdn.net/xxdddail/article/details/18696399 该链接提供的解决方案主要是如下图片:禁用 图片标记的这个选项即可:

  9. 每天一个Linux命令(13):apt命令

    apt-get和apt-cache命令是Debian Linux发行版中的APT软件包管理工具.所有基于Debian的发行都使用这个包管理系统.deb包可以把一个应用的文件包在一起,大体就如同Wind ...

  10. 怎么使用pipenv管理你的python项目

    原文链接:https://robots.thoughtbot.com/how-to-manage-your-python-projects-with-pipenv 翻译者:Jiong 在thought ...