详解Visual Studio调试中断点几个的小技巧

开发 后端
在这里我们将讨论Visual Studio调试中断点几个的小技巧,希望对大家做好调试工作有所帮助。

断点对于Visual Studio调试过程是十分重要的,断点的设置也是为了更好的进行调试。本文将介绍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值。

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

  1. int lcid = System.Globalization.CultureInfo.CurrentUICulture.LCID;  
  2. Console.WriteLine("lcid = {0}", lcid); 

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

1 在Console.WriteLine这一行上设置一个条件断点:

设置条件断点  
图1 设置条件断点

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

  1. Imports System  
  2. Imports EnvDTE  
  3. Imports EnvDTE80  
  4. Imports EnvDTE90  
  5. Imports System.Diagnostics  
  6. Imports Microsoft.VisualBasic  
  7. Imports Microsoft.VisualBasic.ControlChars  
  8. Public Module Module1  
  9.     Sub ChangeExpression()  
  10.         DTE.Debugger.ExecuteStatement("lcid = 0;")  
  11.     End Sub  
  12. 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了?

执行结果
图2 执行结果

数据断点

注意,这个技巧仅对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++项目,我们以下面的源代码为例子:

  1. #include "stdafx.h"  
  2. int g_Variable = 0;  
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.        printf("Before modifying data breakpoints"n");  
  6.        g_Variable = 1;  
  7.        printf("After modifying data breakpoints"n");  
  8.        return 0;  
我们现在要Visual Studio在更改g_Variable的时候中断程序的执行。

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

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

断点监视区域
图3 断点监视区域
 

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

运行提示
图4 运行提示

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

【编辑推荐】

  1. 浅析Visual Studio调试中断点的设置
  2. 图解VS 2010与.NET 4.0多显示器支持
  3. VS 2010和.NET 4的多定向支持
  4. 图解VS 2010和.NET 4起始项目模板
  5. VS 2010和.NET 4第一步:Web.config文件
责任编辑:彭凡 来源: IT168
相关推荐

2009-09-27 08:57:29

Visual Stud

2020-07-09 15:10:20

开发技能代码

2009-12-16 15:44:20

Visual Stud

2021-08-26 05:04:53

JavaScript调试技巧

2009-10-14 09:08:23

Visual Stud

2009-11-30 15:21:38

Visual Stud

2017-04-18 09:27:14

Visual StudNode.js调试

2011-04-02 08:39:27

Visual Stud

2010-12-14 09:15:50

Visual Stud

2010-04-01 15:10:06

Visual Stud

2009-09-04 09:39:15

Visual Stud

2009-04-23 14:05:28

Visual Stud历史调试功能

2013-08-01 15:12:03

Visual Stud

2009-12-03 15:58:33

Visual Stud

2009-12-04 10:35:56

Visual Stud

2009-11-23 14:32:55

Visual Stud

2009-07-31 16:23:00

linux cd命令cd命令技巧

2015-02-04 10:32:57

Objective-CSwift

2010-09-01 08:35:07

Visual Stud

2012-09-17 13:49:31

点赞
收藏

51CTO技术栈公众号