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”窗口输出的表达式,最后自动恢复程序的执行



相关阅读:
Linq to XML 用一句话读出RSS文章列表代码
linux添加新硬盘的详细经过
SQL Server 自动增长清零的方法
Oracle数据库备份与恢复(5):Flashback
拖动一个HTML元素
可以自动轮换的页签 tabs with auto play fucntion
Linux下配置DHCP中继代理
javascript asp教程第八课--request对象
网络管理-Linux系统网络配置详解
css ol有序列表
VBS调用WMI快速关闭IE的脚本
经典收藏:Ajax学习网址大全
javascript实现的多条新闻公告系统
技巧放送:处理Linux内核安全详解
快速导航

Copyright © 2016 phpStudy |