用惯了 VC++ 那方便的调试环境, 尤其是VS 2005 debugger 使用起来更让人得心应手。 在VS 2005 可以很方便的查看变量值, 动态修改内存值,堆栈框架, 各种内存查看窗口。更方便的是当鼠标移动到变量立即显示出变量的地址和该变量值,当该变量是结构体或类获自定义结构时可以很方便的展开查看。结构体的自动展开让我们更快的了解目标变量的结构。
我通常每写完一个下函数或模块就 F5 调试一下,仔细查看各过程变量是否和自己预想的相同. 通过调试可以:
(1) 可以很快地发现程序何处出错
(2) 出现了什么错误
(3) 动态跟踪程序的执行,有助于检查我们在写代码之前的逻辑思维是否正确,程序流程是否合理.
(4) 通过堆栈调用框架,可以确定是哪个函数模块出现了错误
(5) 更重要是,调试使我们更进一步看清了程序本质,不再出现莫名其妙的错误.
(6) 调试是学习汇编语言很有效的途径。
(7) 为我们建立了一种有关该语言的内存布局模型。使我们了解程序运行时内存是怎么占用,堆栈情况.这样出现错误时我们就清除错误出现的根源并可以很快给出解决方法,而不是像有些程序员把错误改正了还不知道为什么随处改了几处代码程序就运行 OK 了.
记得有一次写一个 Delphi 调用 VC DLL 的项目,忘了是哪个项目。当Delphi 调用 VC提供的DLL后,DLL的导出函数在执行期间没有问题,可是在函数退出时却出错.(现在看来这 99.99% 是Call Convention 调用约定不同导致的). 可当时他们delphi 的人1个小时都没有找出为什么出错。 实在不行了, 我开始和他们一起找错,在同时的指导下我开始打开delphi 的调试器动态跟踪程序流程。初次看 delphi 的汇编代码有点头疼(原来$ 等用于 C/C++ 的 0x, 表示是 16 进制). 我就用了 OD (OllyDbg ) 调试。真是万幸,OD 可以源码级调试, 并可以指定汇编代码的类型. 用 OD 跟踪了程序的执行流程,发现函数返回后的返回地址出错,呵呵现在问题根源找到了, VC DLL 中的函数自己把参数退栈但同时delphi 的汇编代码又一次把参数退栈,难怪会出现返回地址错误. 后来我把这个问题和相关的解决方法发到了网上. 整个解决过程不过 10 分钟.
有的时候自己犯懒,在写代码之前不仔细考虑, 写一点调试一点. 现在我经常和公司新来的毕业大学生说: 即使代码不会写, 蒙也要蒙出来。 不管怎么说一个C /C++ 程序员最基本的技能就是熟练使用调试器。现在我一有空就给他们讲调试器的用法包括系统级调试器 windbg ,syser debuger。 softice 早已退出了历史舞台,也只是给他们提一下曾经威震江湖的 SOFTICE 的辉煌历史罢了。
在开发驱动时, 调试器更是必不可, 如果连调试器都不熟,奉劝还是去学习 VB 吧。
使用调试器也并不是一件简单的事情,至少要求你非常熟悉下面几点:
(1) 清楚了解 什么是堆栈,在程序运行时具体做什么用
(2) 清楚了解 CPU 结构, 知道什么是寄存器
(3) 清楚了解 汇编语言, 不要看到汇编代码就怕怕的
(4) 清楚了解 高级语言的代码是怎样在 CPU 上执行的
(5) 了解调试器的实现原理和方法, 以应对调试工具本身的出现的问题,更多时候是为了把调试器作为它用。
(6) 清楚了解 可执行的文件的 2 进制代码结构,这样我们可以把 逆向, 破解 等作为最有趣的休闲娱乐活动
相信上面的几点不是很困难,即使很困难又怎么样,别人是人,你也是人,难道他会你就不会,真没骨气!!
有很多人称是高手,连汇编语言都不了解你还敢说!!丢人!! 不懂汇编别说你是学 C/C++,更别说是搞底层开发的,因为搞底层开发的弟兄们不能和你一起丢人.