《Visual C++ 2010入门教程》系列六:VC2010常见调试技术(转)

2010年07月04日 星期日 下午 10:23

       犹豫了好久,最终还是决定开始这一章,因为我不清楚到底有没有必要写这样的一章,是应该在这里说明一些简单的调试方法,还是干脆直接让大家去看《Visual C++ 2005入门经典》的第10章,因为那里已经说出了我们几乎所有的常见调试方法。

       另外一点就是这一章也许会是《Visual C++ 2010入门教程》系列的最后一章了,因为在入门的这方面,我已经找不到值得和大家分享的经验了,算是黔驴技穷了吧。回头看看这个系列,最初的目的就是为了解决一些初学者常见的问题,教会初学者如何使用VS2010这个工具,因为我也经历过那些阶段,我希望我能帮助那些“曾经的我”少走弯路。

       过去,我们讨论了一些诸如C++和VC有什么区别、怎么用C++做项目这样的问题,介绍了SVN的使用,常见功能的快捷方式,VC配置等等。接下来就是最后的一些与调试相关的东西与大家分享。另外强烈推荐对基本VC调试技术不熟悉的朋友去看看《Visual C++ 2005入门经典》的第十章。

                                

       断点

       没有比断点更常用的了,通过点击代码左边边栏或者移动光标到指定行按F9等都可以添加断点。值得注意的是并非每一行都可以添加断点,这个就留给大家去实践中体会吧。

       通过菜单》调试》窗口》断点或者直接按Alt+F9可以调出断点选项卡,通过选项卡我们可以设置条件断点、数据断点等。


       

        单步和监控

        调试中除了F5之外,另外更常用的估计是F10、F11了,前者是一次一个语句的执行,或者可以看出一行;而后者如果出现能进入的子过程,那么就会进入子过程。这个请大家找个程序,至少要有函数调用的,当断点触发的时候,请自行体验一下F10和F11的效果你就明白了。说白了,实践才是最好的老师,我负责告诉你有这么个东西。

        
        两个选项卡,局部变量和自动变量,它们都负责显示一些当前断住状态下的变量的值,注意,这些只有在程序中断的时候才有意义。自动变量选项卡并非指auto变量,而是指VS帮我们猜想我们可能感兴趣的一些变量的值,或者函数返回值,而局部变量基本上就是本过程的一些变量的值了。

       注意,这些选项卡不仅仅可以用于查看,甚至可以用于你临时修改它们的值,方法就是双击值就可以了,如下图所示:


       这时候你可以把它临时改成false都行哈。

       大家看到监视1了吗?这个选项卡是留给用户的,如果前面的变量太多你不想用滚动条滚来滚去的看就可以在这里输入要监视的变量了:


       这里我检查了当前语言字符串的设置。注意并非什么变量都可以检视,必须是调试器可以为我们推断出来的才行,即调试器知道它的地址是什么。如上图所示有一个特殊的用法$err,hr这个是VS特别的,它的意义相当于让调试器帮你获取GetLastError的值,这在Windows编程的时候非常有用。

       对于一些指针类型的变量我们还可以在监视里面对它做强制转型,比如你的函数传递一个void* p进来,但是你知道这次你传递的是一个Data结构体的指针,而调试器是无法知道这个p指向的是Data,所以你可以在监视中输入(Data*)p。这样调试器会自动帮我们把他当做Data结构体的指针来识别。

        调用堆栈

        调试过程中调用堆栈实在是太重要了,因为它指出了你的程序是正在处于什么状态,是谁调用了谁:

                    

       如果你没有这个选项卡可以通过Alt+7或者调试》窗口》调用堆栈把它调出来。

       运行时也可以获取调用堆栈的,这个需要Windows API的帮助,这个请看我写的这个

      日志

      日志有很多种,你可以写一个专门的日志系统来处理日常的日志工作,但是这里我只说把信息数出到VC的输出窗口,像这样:

                 

       使用Windows API OutputDebugString来实现,当然你也可以对他做一些封装,在程序中在重要的代码部分记录下日志,这对调试很有帮助,你这样会一眼知道哪里出了问题,甚至你可以把调用对战嵌入到这个包装中去:




          通过模块选项卡发现外部模块错误

          
        假设我们依赖于一个外部库Test.dll,这个DLL在系统目录下面有一个,而在Path路径下面还有一个,而他们的版本不同,甚至只是名字相同而内容完全不同。或者其他一系列的类似的问题,都可以通过模块选项卡来察觉,另外这个模块选项卡还告诉了我们我们依赖了那些外部DLL,这在发布的时候很有用,使得我们可以漏掉需要的DLL。

        通过暂停按钮发觉死锁和死循环

        当我们的程序失去响应的时候我们不妨尝试点击调试窗口上面的暂停按钮:

                      

       如果中断(暂停)成功那么我们会看到死锁或者死循环的调用堆栈了。

       断言(assert)
       assert大家应该很熟悉了吧,这是最直接提供错误信息的方法了。特别的,当我们在调试的时候,调试器会帮助我们定位到断言触发的地方。

       暂时就想到这么多,如果您还有其它好Case,一定不要忘了要同大家分享。

       转眼间毕业一年了,感触良多。每当我情绪低落的时候,我就看苏珊大妈的视频,因为苏珊大妈是我的偶像,因为她告诉我有梦想就一定要坚持,当你具备了成功的基础的时候,梦想就会慢慢的实现。

posted @ 2011-01-13 20:31  董雨  阅读(842)  评论(0编辑  收藏  举报