一.案例
我们今天来看一组代码,再VS开发环境调试下面的代码(版本要求VS2013以上,在x86下运行)
#include <stdio.h>
int main()
{
int i = 0;
int arr[] = {1,2,3,4,5,6,7,8,9,10};
for(i=0; i<=12; i++)
{
arr[i] = 0;
printf("hello\n");
}
return 0;
}
我们可以看到我们的光标一直在闪动,一直输出hello,好像陷入了死循环,这是为什么呢?接下来我给大家详细讲解一下。
运行图如下
二.案例分析
我们的局部变量 i 和数组arr是存放在内存中的栈区,而内存中栈区的使用习惯上先用高地址地区,再用低地址空间,所以我们的局部变量 i 先放到高地址空间,然后arr放到低地址空间。而数组的地址是随下标的增大而增大的,故排列图大致为如下
|CC CC CC CC|
arr[0]|01 00 00 00|\
arr[1]|02 00 00 00| \
arr[2]|03 00 00 00| \
arr[3]|04 00 00 00| \
arr[4]|05 00 00 00| \
arr[5]|06 00 00 00| / arr的空间
arr[6]|07 00 00 00| /
arr[7]|08 00 00 00| /
arr[8]|09 00 00 00| /
arr[9]|0A 00 00 00|/
|CC CC CC CC|
|CC CC CC CC|
|00 00 00 00| i的空间
|CC CC CC CC|
我们可以注意到,数组和局部变量间是有空间的,vc6中间无空间,gcc为1个整型空间,vs2013为2个整型空间,因为这多余的空间,直接导致了数组越界访问时会覆盖到其他数值,从而改变其值,从而程序会陷入一些问题,比如说死循环。
在本案例for循环中,i的数据是从0,一直增加到12,但是数组只有10个空间,因此会越界每次访问arr数组i号位置时,都会将该位置内的数据设置为0,当访问到arr[12]时,也会将该位置数据设置为0,而位置恰好为i的位置,即arr[12]恰巧将i设置为0,因此造成死循环。
三.总结
该案例分析示意图大致为下图所示
如果上面内容有问题,请大家及时指出,也欢迎大家分享更多有趣的例子给博主和大家