目录
问题描述
有这样一段代码:
#include<stdio.h>
int main()
{
int i=0;
int arr[10]={0};
for (i=0;i<=12;i++)
{
arr[i]=0;
printf("hehe\n");
}
return 0;
}
在Debug版本下运行结果是:
在Release版本下运行结果是:
请解释在Debug中程序死循环的原因
解题思路
数组内原本只规定有10个元素,但是在循环中i<=12,超出数组三个元素,很明显错误就出在这里,但是我们还需要了解两件事:
- 超出的那三个元素是怎么赋值的?
- 为什么会一直循环?
为解决这两个问题我们就需要去进行调试,我们可以直接看数组的内存就可以了,看数组中的元素是怎么赋值的,
下图就是arr数组所存的内容:
我们可以看到,arr[10]、arr[11]、arr[12]虽然已经“非法”,但是仍然被创造出来了,而且也都被赋值为0,这样我们就解决了第一个问题,那么第二个问题,为什么程序会一直循环?
按照循环的条件,i<=12程序就会停止,但是出现了死循环,所以应该是循环的条件随着循环的执行出现了问题,那么我们就需要看看i的地址和循环中的数组地址是否有相关。
&arr[12]和i的地址
我们发现,i的地址竟然跟arr[12]的地址一模一样,到这里我们就知道了这是怎么一回事了
死循环产生原因
数组超出了所规定的的限制,随着循环的执行,依然会给数组进行赋值,而在这里就出现了问题,随着数组元素的非法越界,导致最后一个数组元素也就是arr[12]的地址跟循环条件中的i的地址重合了,所以随着arr[12]被赋值为0,而导致i的值也被赋值为0,所以循环就会变成死循环。
画图解释一下
数组的地址本来是在i地址的后面,但是随着循环的执行,数组中元素的地址不断往高地址中申请,最后导致arr[12]的地址跟循环条件中的i的地址重合了,所以i重新赋值为0,就导致了死循环。
为什么问题只会在Debug中出现是因为:
Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
总结
- 栈区的默认使用:先使用高地址处的空间再使用低地址处的空间
- 数组随着下标的增长地址是由低到高变化
- vc6.0环境下i<=10就死循环了
- gcc编译器 i<=11就死循环了
- VS2013 i<=12死循环