【文章标题】: VC6.0中调试C语言程序简析
【文章作者】: evilkis
--------------------------------------------------------------------------------------
VC6.0中调试C语言程序方法简析
1..调试工具简介:
VC6.0中有两个应用比较频繁的调试工具:
(1)Memory窗口:其作用即查看相应地址中存放的内容,如图1 

最左边一列为地址 右边四列的内容为内存中的内容,以16进制表示,最后一列为内存内容 的文本显示。
(2)Watch窗口:其作用是监控表达式在程序运行过程中值的变化;其中要监控的表达式是我们自己输入的,如图:
 
要查看那个变量的值的变化就在Name那一列输入变量的名字即可。
2..实战应用
有人说软件开发的能力一看设计能力,二看调试水平,可见调试能力对我们写程序的人来说是一项必须要掌握的技能,调试程序不仅仅可以帮助我们找出程序中的错误还能帮助我们更好的理解相关的C语言内部的东西,那我们现在就来简单的实战一下吧,
首先简单说一下调试常用的几个调试快捷键
当我们进入调试状态时在VC菜单栏中会出现一个Debug工具栏:其最常用的几个快捷键如下
(1)  (Step Over)F10:单步执行,遇到函数调用时,执行完函数调用返回到下一条语句。
(2) (Step Into)F11:单步执行,遇到函数调用时进入到函数中执行(即进入到函数的实现代码中执行)
如何进入调试状态:
进入调试状态有很多方法简单说两种:
(1)在程序中下个断点,然后按F5
(2)直接按F10

1..调试第一个程序hello world!,


 
按F10进入调试状态:一直按F10执行到size_t i=strlen(a);这句在右侧watch窗口Name下输入&a,然后拖到Memory窗口,或者直接在Memory窗口输入&a;
 
如上图 可知字符数组的首地址为0012ff74,共有12个元素,a[0]在内存中为68(注意这里是16进制表示的)转换为10进制为104,相应的ascii码为h,以此类推,此外我们会发现a[11]在内存中为00,其ascii码为空字符即'\0',所以此时我们应该能理解字符串在字符数组中是以\0结尾的吧!


2.看一下数组名与数组首地址的关系
还是上面的程序 我们在Watch窗口Name列中输入a和&a,和&a[0]如图:
 
通过这个可知a= =&a= =&a[0]也就是数组名就是数组的首地址,他是一个地址常量即指针常量指向"hello world"这个字符串,所谓指针常量即指针的值不能改变,但可以改变它所指向的内容,而常量指针是指 指针的值可以改变但不能改变它所指向的内容。

3.看一下多字节数据在内存中的存储方式:
程序如下:
 
按F10进入调试状态,单步执行到 i=10这一行,如图
 
可知所有未初始化的int型变量都在内存中为CCCCCCCC,在执行一步,可以看到
 
地址0012ff7c处的值为0A000000,因为int型数据在内存中占4个字节,可以用sizeof这个操作符算一下,内存中的数据是以16进制数字表示的所以一个字节要存放两位16进制数,显然0A000000和十进制数10不匹配,这就到了我们了解多字节数据在内存中的存储方式了:下面摘自《加密与解密》第三版第一章的内容

多字节数据的在内存中的存放实际与CPU有关,常见的Intel系列的芯片使用的编码方式属于Little-Endian类(这也是我们大多数使用的电脑的cpu类型),另外的是某些RISC架构的CPU,如IBM的Power-PC等属于Bid-Endian类:
Little-Endian:低位字节存入地地址,高位字节存入高地址,反序排列
如将12345678h写入以100h开始的内存中结果为
             ------|----|----|---|---|---------
       100h|78h | 56h|34h|12h|
         -----|----|----|---|---|--------
                   ----------------------->地址变高
8个2进制位是1个字节 4个2进制位表示一个16进制数字所以78h要占一个字节
看到这里我们因该知道在我们大部分机器里面的数据存贮应该是逆序吧,所以上图中的值应该是0000000A,转换成10进制正好是10。看到这里我们感觉到调试的重要性了吧呵呵


4.调试一下数组越界的程序,众所周知C语言是不检查数组越界的,所以我们在编写程序的时候应当小心,尽量把数组的长度定义成符号常量。
下面的程序改自科锐back老师来测试大家C语言功底的第二道题目:原题目在http://bbs.pediy.com/showthread.php?t=51839

程序如下:
 
此程序在Debug模式下运行是个死循环,原因就是数组越界
按F10我们调试一下,单步执行到for循环,然后在Watch窗口输入a,和&i,来查看数组的首地址和变量i的地址如图:
 
可知数组a的首地址为0x0012ff68,而i的地址为0x0012ff7c,通过计算可知,在a[4]后的长度为4字节的内存区域里存放的就是i的值了,单步执行for循环执行5次,我们会发现数组越界地址0x0012ff7c被置为0,如图:
 
即i=0;故而又满足循环条件,所以又会循环,也即此程序会无限循环如下图:


好了就到这里了,写的比较菜,都是些基础知识,最基本的应用,主要目的就是了解Memory和Watch这两个工具,用他们观察内存观察程序的运行。关于调试的更多的应用需要我们自己去慢慢体会,写的不好的地方欢迎指正大家共同进步!