艾伟_转载:Visual Studio调试之断点进阶篇

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 文章导航Visual Studio调试之断点基础篇Visual Studio调试之断点进阶篇Visual Studio调试之断点技巧篇在上一篇文章Visual Studio调试之断点基础篇里面介绍了什么是断点,INT 是Intel系列CPU的一个指令,可以让程序产生一个中断或者异常。

文章导航

Visual Studio调试之断点基础篇

Visual Studio调试之断点进阶篇

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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
存储 程序员 编译器
Visual Studio 2022 程序员必须知道高效调试手段与技巧(下)终章
Visual Studio 2022 程序员必须知道高效调试手段与技巧(下)终章
153 0
|
1月前
|
微服务
微服务实践之使用 Visual Studio 2022 调试Dapr 应用程序
微服务实践之使用 Visual Studio 2022 调试Dapr 应用程序
41 2
|
6月前
在visual studio中调试程序 管理员权限添加
在visual studio中调试程序 管理员权限添加
118 0
|
12月前
VisualStudio 调试 添加命令行参数
VisualStudio 调试 添加命令行参数
79 0
|
存储 程序员 C++
Visual Studio 2022 程序员必须知道高效调试手段与技巧(中)
Visual Studio 2022 程序员必须知道高效调试手段与技巧(中)
245 0
|
程序员 C++ Windows
Visual Studio 2022 程序员必须知道高效调试手段与技巧(上)
Visual Studio 2022 程序员必须知道高效调试手段与技巧(上)
253 0
|
开发框架 .NET C#
Visual Studio Code调试和发布ASP.NET Core Web应用
Visual Studio Code调试和发布ASP.NET Core Web应用
165 0
|
Rust NoSQL 编译器
Rust在Visual Studio Code中调试提示debug type is not supported
Rust在Visual Studio Code中调试提示debug type is not supported
295 0
Rust在Visual Studio Code中调试提示debug type is not supported
|
前端开发 API 开发者
.NET Web应用配置本地IIS(实现Visual Studio离线运行与调试
.NET Web应用配置本地IIS(实现Visual Studio离线运行与调试
359 0
.NET Web应用配置本地IIS(实现Visual Studio离线运行与调试
|
存储 JSON JavaScript
简说Visual Studio代码进行调试
前端编程很有趣,开发人员有能力创建他们想要的任何东西,任何效果。不幸的是,当遇到bug时,这种乐趣就会消失。JavaScript开发人员可能首先想到的是alert、console.log语句。添加console.log()是可视化代码状态的一种快速方法。
310 0
简说Visual Studio代码进行调试
下一篇
无影云桌面