c语言---访问越界之后死循环的原因

本文详细解释了在VS2022、X86、Debug环境下,一个看似简单的程序为什么会陷入死循环,关键在于数组下标越界时覆盖了循环变量i,导致两者地址相同。作者还探讨了栈区内存使用习惯和编译器对内存分配的影响。
摘要由CSDN通过智能技术生成

死循环的概念

简单来说,死循环就是指无法靠自身的控制终止循环,在编程中,则是靠自身控制无法终止的程序。即在某一时刻,当程序遇到循环判断语句使条件一直成立时,导致此时该程序始终在执行,跳不出循环,程序不能自己正常结束。

环境

在这里插入图片描述

在VS2022、X86、Debug 的环境下,编译器不做任何优化的话,看看下⾯代码执⾏的结果

题目代码

这个代码严重依赖环境。

#include <stdio.h>
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("牛逼\n");
	}
	return 0;
}

运行结果

在这里插入图片描述
在这里可以看到一直在打印牛逼这两个字,这就是进入了程序死循环。

对代码发生情况进行解释

对这个代码进行调试按F10走起,到下面这里
在这里插入图片描述
可以看到现在已经打印了10个牛逼
在这里插入图片描述
然后我们再继续按F10看看会怎么样呢?
在这里插入图片描述
可以看到i的值也跟着arr[12]一起变成0了。那么为什么i也会跟着改呢?但凡是不是i不改的话,i是不是通过i++,然后就变成13了就跳出了这次循环。但是并没有这样,那为什么看到i的值也跟着arr[12]一起变成0了呢?难道i和arr[12]在同一块空间?
为了验证这个问题,我们取i的地址和arr[12]的地址,
在这里插入图片描述

可以看出i的地址和arr[12]的地址一模一样,这就说明,改arr[12],i也会跟着改。然后又重新开始,这个i永远也不可能等于13,然后就出现了程序死循环。

对i的地址和arr[12]地址一样的解释

1.栈区内存的使⽤习惯是从⾼地址向低地址使⽤的,所以变量i的地址是
较⼤的。arr数组的地址整体是⼩于i的地址。
2. 数组在内存中的存放是:随着下标的增⻓,地址是由低到⾼变化的。所以根据代码,就能理解为什么是左边的代码布局了。如果是左边的内存布局,那随着数组下标的增⻓,往后越界就有可能覆盖到i,这样就可能造成死循环的。这⾥肯定有人有疑问:为什么i和arr数组之间恰好空出来2个整型的空间呢?这⾥确实是巧合,在不同的编译器下可能中间的空出的空间⼤⼩是不⼀样的,代码中这些变量内存的分配和地址分配是编译器指定的,所以的不同的编译器之间就有差异了。所以这个题⽬是和环境相关的。
在这里插入图片描述
从这个理解我们能够体会到调试的重要性,只有调试才能观察到程序内部执⾏的细节,就像医⽣给病⼈做B超,CT⼀样。

注意

栈区的默认的使⽤习惯是先使⽤⾼地址,再使⽤低地址的空间,但是这个具体还是要编译器的实现,⽐如:
在VS上切换到X64,这个使⽤的顺序就是相反的,在Release版本的程序中,这个使⽤的顺序也是相反的。
用VS2022、X64、Debug 的环境运行一遍:
在这里插入图片描述
运行结果
在这里插入图片描述
这个代码换个环境就不行了,就不会出现程序死循环的现象。

总结

#include <stdio.h>
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("牛逼\n");
	}
	return 0;
}

这个题目代码是在环境(VS2022、X86、Debug)的环境下会出现程序死循环,再次强调这个题目代码强烈依赖环境.。
在这里插入图片描述
欧耶!!!!!我学会啦!!!!!!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值