这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战」
上一篇文章的问题代码,我认为有必要单独拿出来讲讲! 从代码角度,带你手把手调试(上) - 掘金 (juejin.cn)
回顾上文:
一个有问题的代码
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i <=12; i++)
{
arr[i] = 0;
printf("hehe\n");
}
return 0;
}
执行结果:死循环打印hehe
为了发现问题:打印第几次打印
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i <=12; i++)
{
arr[i] = 0;
printf("hehe\n");
printf("第%d次打印\n",i);
}
return 0;
}
i不能变为12
调试结果:
将第数组元素下标为12的值也改成0时,i也恢复为0,所以造成了死循环
**为什么呢?
猜想两个占用同一块空间
->验证
深入理解上述程序err原因
栈区先使用高地址,再使用低地址. 先定义变量i,所以i在高地址位置,然后再定义数组,二者相隔几个地址未知
arr和i中隔了几个元素是未知的,取决于编译器
变量和数组相隔距离
VC6.0中: arr和i是紧挨着的
VS2013-VS2019 arr和i中间有两个元素
gcc: arr和i之间放一个元素
所以在VC6.0条件下,arr[10],写成i <= 10时就死循环了
如何解释:
i和arr是局部变量,放在栈区,栈区的使用习惯是先使用高地址,再使用低地址
画出栈区内存,上面低地址,下面高地址,先把高地址的空间使用了
i在下面创建,arr在上面创建,
又因为随着数组下标的增长,元素的地址又低到高变化
随着数组下标的越界访问,就可能覆盖循环变量i(二者占用同一块空间)
问:当i和arr的创建反过来时:直接报错,不会死循环
因为内存布局发生变化
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i <=12; i++)
{
arr[i] = 0;
printf("hehe\n");
printf("第%d次打印\n",i);
}
return 0;
}
执行结果:报错
注意
程序越界有一个报错的时间点,程序停下来时才报错,死循环了没时间报错
若改成release版本:
执行结果:打印13个hehe
在Debug情况下: i确实在数组后面存放, i的地址比数组地址大
而在Release版本:数组的地址更大 编译器进行了优化了,因为考虑到放后面可能出错
这也证明了Release版本确实可以优化
今天就先到这吧~感谢你能看到这里!希望对你有所帮助!欢迎老铁们点个关注订阅这个专题! 同时欢迎大佬们批评指正!