软件调试总结及分享

1、  软件调试对软件开发的意义。

通过软件调试,我们可以更深刻的理解语言深处的实现原理。如利用Windbg深入理解变量的存储模型:我们可以通过windbg验证查看C++书上关于各种类型变量存储区域的说明,简单来说就是全局变量和静态变量会被编译到可执行文件的数据节(分只读和可读写)中, 非静态的局部变量则分配在堆栈(stack)上,而new(malloc)出来的内存则分配在堆(heap)上。

有人做过调查,80%以上的程序员是把一半以上的时间用在程序调试上的。很多项目的延期以及程序员的加班也与要调试某个/些棘手的BUG息息相关。学习调试原理是提高调试效率的根本途径。强烈建议大家提高对软件调试技术的重视程度,有计划,有意识的学习一些基本的软件调试原理。

2、  调试器工作原理

CPU有一个单独的执行序列,会一条指令一条指令的顺序执行。调试器需要系统和硬件CPU的软硬中断的支持,将当前要执行的汇编指令流保存起来,保存好当前上下文,寄存器,变量,线程等的数据,并中断到调试器,跳转到一个预定义的地址处去执行。这个地址上会有一个中断处理例程,当中断处理例程完成它的工作后,CPU就继续从之前停止的地方恢复执行。

调试器应该具有的基本功能:

A、 可以控制被调试程序的执行,包括将其中断到调试器,单步跟踪执行,恢复运行,设置断点等

B、 可以访问被调试程序的代码和数据,包括读写数据,观察和反汇编成代码,读写寄存器等

 

符号文件对调试器的支持:

符号文件通常包含以下内容:

· 全局变量的名字和地址

· 函数名, 地址及其原型

· 帧指针优化(Frame Pointer Optimization, FPO)数据

· 局部变量的名字和地址

· 源文件路径以及每个符号的行号

· 变量, 结构等的类型信息

 

如果拥有了这个 PDB符号文件,那么我们便可以用它来调试并跟踪到EXE/.DLL 内部

 

3、  常见的需要调试的问题。

运行时出错,内存出错,变量、指针是否越界,指针是否为空等、例外没有处理。

4、  windbg常用的调试的命令

.reload/!sym    加载符号文件

lmf    列出当前进程中加载的所有模块

r    显示和修改寄存器上的值

d    显示内存地址上的值

e    修改内存地址上的值

!address    显示内存页信息

s    搜索内存                                 

!runaway    检查线程的cpu消耗

~    切换目标线程

k,kb,kp,kv,kn    检查callstack- DisplayStack Backtrace.

u    反汇编

x    查找二进制符号的地址

dds    打印内存地址上的二进制值,同时自动搜索二进制值对应的符号

.frame    在栈中切换以便检查局部变量

dt    格式化显示资料

wt watchand trace data,  可以跟踪一个函数的所有执行过程,并且给出统计信息

bp    设定断点

bd breakpoint disabled,   取消断点

ba breakon access,   设定访问断点

sx    设定exception断点

.dump    保存dump文件

5、  实例分享。

 

6、  其他辅助工具的使用

 见另一篇日志,崩溃、性能优化工具简单说明及总结

  

7、参考资料:

http://blog.jobbole.com/23632/

https://segmentfault.com/a/1190000010869844

http://advdbg.org/

http://www.cnblogs.com/awpatp/archive/2009/11/08/1598447.html

https://www.cnblogs.com/Gotogoo/p/5381838.html

https://www.cnblogs.com/huangyong9527/archive/2012/08/22/2650948.html

你可能感兴趣的:(VC++,windbg软件调试)