Visual Studio调试之断点进阶篇

在上一篇文章Visual Studio调试之断点基础篇里面介绍了什么是断点,INT 是Intel系列CPU的一个指令,可以让程序产生一个中断或者异常。程序中如果有中断或者异常发生了以后,CPU会中断程序的执行,去一个叫做IDT的部件查找处理这个中断(或者异常)的例程(Handler)。IDT是操作系统在启动的时候初始化的,至于IDT的细节问题,例如什么是IDT,怎样编写一个IDT的例程,怎样 初始化IDT,可以去网上搜索一些资料。

总之,这里我们只要知道,CPU在执行程序指令过程中,碰到INT 3中断程序的执行,CPU然后去IDT表里面找到处理断点的例程入口。这个例程要做的事情就是:

1.       先看看机器里面是不是安装了一个调试器—记住,这一步很重要,之所以重要以后的文章里面会介绍。

2.       如果机器里面没有安装调试器,那么操作系统就会终止程序的执行。

3.       否则操作系统启动调试器,并将调试器附到进程上。

4.       这样,我们才能在调试器里面检查程序内部变量的值。

前面文章里面的INT 3 (或者DebugBreak(),或者Debugger.Break())指令是我们自己在代码里面硬编码进去的,因此我们在Visual Studio里,在相应的代码行里面点一下,出现一个小红球,也就是说Visual Studio在程序指令集某个地方动态地添加了一个INT 3指令。现在的问题来了,Visual Studio是如何在程序中正确找到插入INT 3指令的位置的?

或者更具体一些,我们在源代码(文本文件)里面设置断点的,Visual Studio需要把代码行翻译成在程序指令集中的位置。Visual Studio之所以需要做翻译,是因为通常一行C++或者 C#代码都会对应好几行汇编指令。

因此,Visual Studio需要一个额外的文件来执行这个翻译过程,这个额外的文件叫做调试符号文件(Symbols),是由编译器生成的。Visual Studio系列的编译器,不论是C#、VB.NET还是C++编译器都会生成这个调试符号文件,.pdb 文件。所以如果你花一点时间看看Debug文件夹的话,你就会发现这个文件。

因此我们来看看Visual Studio支持的各种断点,并解释各种断点的实现方式

条件断点

首先我们先看看如何设置条件断点,条件断点有两种,一种是根据触发的次数来设置,另外一种是根据一条预置的条件来设置。

根据触发次数设置

比如说,你有一个循环,循环1000次,你知道有一个BUG总是在500次之后才会出现,因此肯定希望在循环内设置一个断点,但是前面500次都不会触发这个断点,否则连续按500次的F5的确不是一件轻松的差事。

根据预置条件来设置

如果你已经知道一些条件可能会引发Bug,那么根据条件来设置则最合适不过了。如下图所示:

在“断点条件(Breakpoint Condition)”对话框里面,只需要输入一条正常的C#、C++或者VB.NET的语句就可以了(当然,语法是根据你项目里面的源代码语法一致),这条语句的要求是必须返回bool值—否则就不是一个条件了。

第三个还有断点过滤器,当你在断点上,右键点击弹出的菜单里面,会有一个“过滤(Filter)”菜单,它允许你限制将断点仅设置在特定的线程上。这里我就不细讲了,有兴趣的话,可以自己写一个多线程或者多进程程序试试这个功能。

知道断点的原理以后,理解条件断点应该就不会是问题了。

监视断点(Watching Point)

有的时候,你可能需要查看程序内部一些变量的值,但是你又不希望中断程序的执行。例如你在调试一个网络协议栈,一个程序可能在接收数据包,你想看看数据包的格式,但如果中断程序的执行,会导致后续的数据包丢失。

因此,我们一般的做法就是在源代码里面加一些日志记录代码,这样可以将一些变量的值记录下来,以便后续分析。如果日志在产品发布以后还需要的话,在源代码里面加入这些日志代码固然是一个好主意,但是如果你只是想临时看看一些变量的值呢?

这个时候,监视断点就很有用了,Visual Studio的监视断点就可以让你做到在不修改程序源代码的前提下,在调试器窗口中打印一些变量的值。

下图演示了监视断点的用法:

设置监视断点的步骤,或者说是注意事项吧:

1.       设置一个普通的断点

2.       右键单击刚刚设置的断点,在弹出菜单里面选择“When Hit…”

3.       钩选 第一个“打印一条消息(Print a message)”复选框,输入一串文本,默认情况下,你输入的文本会被直接打印到调试的输出窗口里面来。除了:

a.       以$符号开头的几个关键字。比如$FUNCTION就会被替换成断点所在的函数名。其他有一些关键字在“When Breakpoints Is Hit”窗口当中有详细的说明。

b.      使用 大括号 {}包含起来的变量名,这样的字符串会被替换成变量的值。

这下面就是监视断点的效果,注意,你只能在Visual Studio的“输出(Output)”窗口中查看结果。

监视断点相对于日志记录的好处是,你不需要改动源代码,并且重新编译代码。实际上Visual Studio实现监视断点的原理也很简单,就是插入一个普通的断点,断点触发之后处理并且打印在“When Breakpoints Is Hit”窗口输出的表达式,最后自动恢复程序的执行。

Visual Studio调试之断点进阶篇的更多相关文章

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

    原文链接地址:http://blog.csdn.net/Donjuan/article/details/4618717 函数断点 在前面的文章Visual Studio调试之避免单步跟踪调试模式里面我 ...

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

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

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

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

  4. Visual Studio 调试技巧:10 篇热文汇总

    本文精选了 DotNet  2017年11月份的10篇热门文章.其中有技术分享.技术资源. 注:以下文章,点击标题即可阅读 <Visual Studio的调试技巧 > 调试技巧是衡量程序员 ...

  5. VISUAL STUDIO 调试

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

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

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

  7. Visual Studio调试之符号文件

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

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

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

  9. Visual Studio 调试系列12 远程调试部署在远程计算机IIS上的ASP.NET应用程序

    系列目录     [已更新最新开发文章,点击查看详细] 要调试已部署到IIS的ASP.NET应用程序,请在部署应用程序的计算机上安装并运行远程工具,然后从Visual Studio附加到正在运行的应用 ...

随机推荐

  1. COJ 0538 购物问题

    购物问题 难度级别:C: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 由于换季,ACM商场推出优惠活动,以超低价格出售若干种商品.但是,商场 ...

  2. 【模拟】XMU 1054 Hacker

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1054 题目大意: 多组数据,n=0结束.给定n(n<=1 000 000)和n个 ...

  3. Java学习日记-2.1 运算符

    1. 赋值运算符 赋值运算符是有值的 int i; System.out.println(i = 5); //输出5 正因为赋值运算符有值,所以可以可以连等地赋值 int j,k,l,m,n; j = ...

  4. [Design Pattern] DAO Pattern 简单案例

    Data Access Object Pattern, or DAO Pattern, 即 DAO 模式,用于分离底层的数据访问接口,已经上层的业务逻辑. 下面是 Dao 模式的一个简单的案例. St ...

  5. POJ 3669 广度优先搜索

    题意:巨大流星雨即将袭来.每个流星会对击中的地方以及周围(上下左右四格)造成破坏.Bessie开始时位于(0, 0)位置,并希望逃到一处不会被袭击到的地方(在第一象限内).已知每移动一格需要1个时间单 ...

  6. 基于deb包快速搭建内外apt源

  7. Back to Basics: Using KVO

    One of the things I like most about Apple’s iOS SDK is the consistent and easy-to-use API they provi ...

  8. Android中如何像 360 一样优雅的杀死后台服务而不启动

    Android中,虽然有很多方法(API或者shell命令)杀死后台`service`,但是仍然有很多程序几秒内再次启动,导致无法真正的杀死.这里主要着重介绍如何像 360 一样杀死Android后台 ...

  9. android Bluetooth(官方翻译)

    Bluetooth Using the Bluetooth APIs, an Android application can perform the following: 使用蓝牙APIs,一个And ...

  10. C#中hashtable的赋值、取值、遍历、排序操作

    一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其 ...