vs调试技巧的总结

来源:互联网 发布:jquery json 查找 编辑:程序博客网 时间:2024/05/17 23:05

调试是软件开发周期中的一个很重要的部分,有时很有挑战性,有时候则让程序员迷惑,有时候让程序员发疯,但是。可以肯定的是,对于任何不是太那个微不足道的程序来说,调试是不可避免的。近年来,调试工具的发展已经使得很多调试任务简单省时了。 本文总结了十个调试技巧,当你使用VS的时候可以节省你很多时间。


                  http://blog.csdn.net/lanbing510/article/details/8545483




Visual Studio原生开发的10个调试技巧

最近碰巧读了Ivan Shcherbakov写的一篇文章,《11个强大的Visual Studio调试小技巧》。这篇文章只介绍了一些有关Visual Studio的基本调试技巧,但是还有其他一些同样有用的技巧。我整理了一些Visual Studio(至少在VS 2008下)原生开发的调试技巧。(如果你是工作在托管代码下,调试器会有更多的特性,在CodeProject中有介绍它们的文章),下面是我的整理的一些技巧:

1. 异常中断 | Break on Exception

2. Watch窗口中的伪变量| Pseudo-variables in Watch Windows

3. 符号越界后查看堆对象 |

4. 查看数组的值

5. 避免进入不必要的函数

6. 从代码启动调试器 | Launch the debugger from code

7. Output窗口打印

8. 隔离内存泄漏

9. 调试发行版 | Debug the Release Build

10. 远程调试

 

技巧1: 异常中断

在处理被调用之前,异常发生时可以启动调试器进行中断,可以让你在异常发生后立即调试程序。操作调用栈便于你去查找异常发生的根本原因。

Vistual Studio允许你去指定想要中断的异常类型或者特殊异常。选择菜单Debug>Exceptions弹出对话框,你可以指定原生的(或者托管的)异常,除了调试器自带的一些默认异常,你还可以添加自己的自定义异常。

下面是一个std::exception异常抛出时调试器中断的例子。

· 1  异常抛出时如何中断

· 2  如何添加新的异常

 

技巧2Watch窗口中的伪变量

Watch窗口或QuickWatch对话框提供一些特定的(调试器可识别的)变量,被称为伪变量。文档包含以下:

· $tid—–当前线程的线程ID

· $pid——进程ID

· $cmdline———-启动程序的命令行字符串

· $user———-正在运行程序的账户信息

· $registername—–显示寄存器registername的内容

不管怎么样,关于最后一个错误的伪变量是非常有用的:

· $err——–显示最后一个错误的错误码

· $err,hr—显示最后一个错误的错误信息

技巧3:符合越界后查看堆对象

有时候,在调试符号越界后,你还想查看对象的值,这个时候,watch窗口中的变量是被禁用的,不能再查看(也不能更新),尽管对象仍然存在。你如果知道对象的地址,可以继续充分地观察它。你可以将地址转换为该对象类型的指针,放在watch窗中。

下面的例子中,当单步跳出do_foo()之后,_foo不能再被访问。但是,将它的地址转换为foo*后,就可以继续观察这个对象。

 

技巧4:查看数组的值

如果你在操作一个很大的数组(我们假设至少有几百个元素吧,但是可能更少),Watch窗口中展开数组,查找一些特定范围内的元素很麻烦,因为你要不停地滚动.如果数组是分配在堆上的话,你甚至不能在watch窗口中展开数组元素.对此,有一个解决办法。你可以使用(array+ <offset>),<count> 去查看从<offset>位置开始的特定范围的<count>元素(当然,这儿的数组是你的实际对象)。如果想查看整个数组,可以简单使用array,<count>.

如果你的数组是在堆上,你可以在watch窗口中将它展开,但是要查看某个特定范围的值,用法稍有不同:((T*) array + <offset>),<count>(注意这种用法对于堆上的多维数组也有效)。但是这种情况下,T是指数组元素的类型。

如果你在用MFC,并使用其中的’array’容器,像CArray, CDWordArray,CStringArray等等。你当然可以使用同样的过滤方法。除此之外,你必须查看arraym_pData成员,它是保存数据的真实缓存。

 

技巧5:避免进入不必要的函数

很多时候,你在调试代码时可能会进入到你想跳过的函数,像构造函数,赋值操作或者其他的。其中最困扰我的是CString构造函数。下面是一个例子,当你准备单步执行take_a_string()函数时,首先进入到CString的构造函数。

1

2

3

4

5

6

7

8

void take_a_string(CString const &text)

{

}

 

void test_string()

{

   take_a_string(_T("sample"));

}

幸运的是可以告诉调试器去跳过哪些方法,类或者整个命名空间。实现它的方法也已经改变了,回到使用VS6的日子,通常是通过autoexp.dat文件来指定的。Vistual Studio 2002改成了使用注册表设置。想要跳过一些函数,你需要在注册表里添加一些值(详情如下):

1. 实际位置取决于你使用的Vistual Studio版本和操作系统平台(x86x64,因为注册表只能在64位的Windows下浏览)

2. 值的名字是数字,代表规则的优先级;数字越大,优先级越高。

3. 值数据是一个正则表达式的REG_SZ值,用于指定怎样过滤和执行。

为了避免进入任何CString方法,我添加了下面的规则:

 

有了这个,即使你强制进入上例中的take_a_string(),调试器也会跳过CString的构造函数。

技巧6:从代码启动调试器 Launch the debugger from code

你可能很少需要将调试器附加到程序中,但你不能在Attach窗口这样做(可能因为中断发生太快而没有捕获到),你也不能一开始就在调试器中启动程序。你可以在程序中产生中断给调试器一个机会通过调用内部的_degbugbreak()来附加。

1

2

3

4

void break_for_debugging()

{

   __debugbreak();

}

实际上还有其他的方法来完成,例如触发中断3,但这仅仅适用于x86平台(C++64位不再支持ASM)。另外还有DebugBreak()函数,但它的使用不怎么简便,所以这里推荐使用内部方法。

1

__asm int 3;

   程序运行内部方法时会停止运行,这时你就有机会将调试器附加到该进程。

 

 

 

技巧7:在output窗口打印

通过调用DebugOutputString可以在调试器的output窗口显示一段特定的文本。如果没有附加的调试器,该函数什么也不做。

 

技巧8:隔离内存泄漏

内存泄漏是在原生开发中的一个很重要的问题,要检测内存泄漏是一个很严峻的挑战,尤其是在大型项目中。Vistual Studio可以提供检测内存泄漏的报告,还有其他的一些应用程序(免费的或商业的)也可以帮助你检测内存泄漏.有些情况下,在一些内存分配最终会导致泄漏时,可以使用调试器去中断。但是你必须找到可再现的分配编号(尽管没那么容易)。如果能做到这一点,执行程序时调试器才会中断。

 我们来看下面的代码,分配了8个字节,却一直没释放分配的内存。Visual Studio提供了造成内存泄漏的对象的报告,多运行几次,会发现一直是同一个分配编号(341)。

1

2

3

4

5

6

7

8

9

void leak_some_memory()

{

   char* buffer = new char[8];

}

 

Dumping objects ->

d:\marius\vc++\debuggingdemos\debuggingdemos.cpp(103) : {341} normal block at 0x00F71F38, 8 bytes long.

 Data: <        > CD CD CD CD CD CD CD CD

Object dump complete.

在一个特定的(可复现的)位置中断的步骤如下:

1. 确定你有足够的关于内存泄漏的报告模式(参考 使用CRT库检测内存泄漏)

2. 多次运行程序直到你能在程序运行结束后的内存泄漏报告里找到一个可复现的分配编号,例如上个例子中的(341

3. 在程序一开始的地方设置一个断点以便你能够尽早地进行中断。

4. 当最初的中断发生时,watch窗口的Name栏里会显示:{,,msvcr90d.dll}_crtBreakAlloc,在Value栏里写入你想要查找的位置编号

5. 继续调试(F5

6. 程序执行到指定位置会停止,你可以使用调用栈被指引找到被该位置触发的那段代码。

遵循这些步骤, 在上个例子中,使用分配的编号(341)就可以识别内存泄漏的起因。

 

技巧9:调试发行版

调试和发布是两个不同的目的。调试配置是用于开发的,而发布配置,顾名思义,是用来作为程序的最终版本,因为它必须严格遵循发布的质量要求,该配置包含优化部分和调试版本的中断调试的设置。而且,有时候,要像调试调试版本一样去调试发行版。要做到这一点,你需要在配置里做一些改变。但是这种情况下,你就不再是在调试发行版,而是调试和发行的混合版。

 

你还应该做一些事儿,以下是必须要做的:

1. 配置C/C++ >General>Debug Information Format应该为 “Program Database(/Zi)”

2. 配置C/C++ >Optimization>Optimization应该为”Disabld(/Od)”

3. 配置Linker>Debugging>Generate Debug Info应该为”Yes/(DEBUG)”

如图所示:

 

技巧10:远程调试

另一个重要的调试就是远程调试,这是一个更大的话题,多次被提到,这里我只做一下简单的概括:

1. 你需要在远程机器上安装远程调试监控

2. 远程调试监控必须以管理员身份运行,并且用户必须属于管理员组

3. 在你运行监控时,会开启一个新的服务,该服务的名字必须用Visual StudioAttach to Progress窗口的Qualifier组合框的值。

 

 

1. 远程和本地机器上的防火墙必须允许Visual Studio和远程调试监控之间能够通信

2. 想要调试,PDB文件是关键;为了能够让VisualStudio自动加载它们,必须满足以下条件:

1)本地的PDB文件必须可用(在远程机器的相同路径下放置一个对应的模块)。

 2) 远程机器上的托管PDB文化必须可用。

远程调试监控下载:

· Visual Studio 2008 Service Pack 1 Remote Debugger

· Microsoft Visual Studio 2010 Remote Debugger

结束语

Ivan Shcherbakov那篇文章和我这篇文章提到的调试技巧,在大多数的调试问题中都是必不可少的。想要知道更多的关于调试技巧的知识,建议阅读文章中提供的额外阅读。

 


1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 快递自提柜坏了怎么办 快递运送坏了怎么办 顺丰寄东西坏了怎么办 顺丰邮东西坏了怎么办 快递中途包装破损怎么办 信封封条破损了怎么办 奶粉罐子扁了怎么办 奶粉邮寄爆罐怎么办 奶粉打开爆罐怎么办 海关包裹被扣怎么办 天猫未收货显示签收怎么办 物流显示包裹破损怎么办 快递寄鞋盒破损了怎么办 邮寄东西碎了怎么办 快递屏幕碎了怎么办 快递东西破了怎么办 收快递东西损坏怎么办 快递寄新鲜东西怎么办 寄东西损坏了怎么办 顺丰写错电话号码已签收怎么办 快递包装扔了怎么办 淘宝快递损坏了怎么办 买家寄过来破损怎么办 卖家发假单号自动签收怎么办 ems快递包裹破损怎么办 微波炉外包装扔掉退货怎么办 交警判决不服该怎么办 如果判决不服该怎么办 学不会看卡尺怎么办 我学不会卡尺怎么办 卡尺表针歪了怎么办 电喷摩托车没电怎么办 话筒插头坏了怎么办 电柜接线看不懂怎么办 发动机缸盖渗油怎么办 吃杏吃多了肚子难受怎么办 住院单据丢了怎么办 医院单据丢了怎么办 购房单据丢了怎么办 废电瓶回收手续怎么办 ai置入图片过大怎么办