`
tansitongba
  • 浏览: 483255 次
文章分类
社区版块
存档分类
最新评论

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值(当然我最后找到了,下一个技巧将告诉你我是怎么找到的),然而我又不想重启系统(呃……也许我就是那种宁愿花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,靠,调过了,重来,F11F10,……

这种情况下,数据断点就很有用了,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 2012 Tools for Unity

    Visual Studio 2012 Tools for Unity断点调试

    Visual Studio Debug实战教程之断点操作

    前言 调试技巧是衡量程序员水平的一个重要指标.掌握好的调试技巧与工具的使用方法,也是非常重要的. ...其实,关于断点,Visual Studio 有很多的高级功能,有些简直就是调试利器啊。 本次教程将介绍 Visual Stu

    Visual Studio中js调试的方法图解

    主要介绍了Visual Studio中JS调试的方法,需要的朋友可以参考下

    Visual Studio 2013 Tools for Unity

    Visual Studio 2013 Tools for Unity断点调试

    浅析Visual Studio Code断点调试Vue

    这篇文章将介绍如何配置 Visual Studio Code 和 Chrome 来完成直接在 VS Code 断点调试代码, 并且在VS Code的调试窗口看到Chrome中console相同的值。 设置 Chrome 远程调试端口 首先我们需要在远程调试打开的状态下...

    如何设置IE BHO在Visual Studio中的调试步骤

    图文描述C#开发BHO时如何如何对BHO代码进行调试,跟踪断点

    Visual Studio 2005 Remote Debugger 32/64位

    或者直接运行或copy本地端的: "Program Files\Microsoft Visual Studio 8\Common7\IDE\Remote Debugger\x86" (2) 远程端:“本地安全策略 - 安全选项 - 网络访问:本地帐户的共享和安全模式”改为:经典-本地...

    分享Visual Studio原生开发的10个调试技巧(2)

    之前关于Visual Studio调试技巧的文章引起了大家很大的兴趣,以至于我决定分享更多调试的知识。以下的列表中你可以看到写原生开发的调试技巧(接着以前的文章来编号)。这些技巧可以应用在VS2005或者更新版本中...

    Visual Studio 2013 Tools for Unity(VSTU 2.3)(unity vs调试工具)

    Visual Studio 2013 Tools for Unity(VSTU 2.3) , vs2013官网最新版本2.3,之前在网上下了vstu1.9自己这边用不了。强烈建议去官网下载。之所以上传,是因为,我这边总是下载失败,可能有和我一样的人。(csdn 不...

    用于Rust的Visual Studio扩展-Rust开发

    用于Rust的Visual Studio扩展当前正在开发中,功能不完整。...功能基于突出显示“货物语法”的项目支持自动完成转到定义MSVC和GNU工具链的调试条件断点“监视”窗口(具有更改运行时状态的能力)Immedi

    10个VisualStudio原生开发调试技巧

    当数据所在内存位置变化时,调试器将会中断。然而,这是唯一可能在一个时间创建4这样的硬件的数据断点。数据断点只能在编译的过程中添加,可以通过菜单(编译>新断点>新数据断点)或者通过断点窗口来添加。在下面的...

    python tools for visual studio 2010

    在VS平台上开发python程序,亲测有效,可进行断点调试,只要安装就行不用进行任何配置

    C#客户端程序Visual Studio远程调试的方法详解

    Win10等不同版本的系统去做兼容性调试,也有时候会去针对特别的显卡,无线网卡等等硬件设备的机器做优化,有一种较优的方案,那就是使用Visual Studio的远程调试功能,可以直接将测试机作为调试目标,直接跟踪断点和...

    Nsight Visual Studio Edition 单机调试+双机调试CUDA程序

    结合网上教程之后自己配置Nsight并进行单机和双机调试的过程。32位Win7+VS2008 + CUDA4.0 + Nsight环境,实现对CUDA核函数的调试,可以进入断点观察变量值。

    Mac Catalina系统 VScode C/C++ 代码调试 断点无效/不起作用

    更新之后的第二天,发现打的断点无效了,调试如同直接运行。 百度没搜到,只有一个知乎的线索,但没多讲。顺藤摸瓜,开始磕VScode官方英语教程,附上链接 https://code.visualstudio.com/docs/cpp/config-clang-mac ...

    Visual Studio调试技巧汇总

    调试是软件开发周期中很重要的一部分。它具有挑战性,同时也很让人疑惑和烦恼。总的来说,对于稍大一点的程序,调试是不可避免的。最近几年,调试工具的发展让很多调试任务变的越来越简单和省时。 1 悬停鼠标查看...

Global site tag (gtag.js) - Google Analytics