源于《C陷阱与缺陷》----研究程序死循环问题

本题来源于《C陷阱与缺陷》这本书,从本质上讲解程序死循环的原因,关键在于栈的空间使用方式。

研究程序死循环的原因

题目1:
在VS2019 X86环境下测试:

int main()
{
	int i;
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	for (i = 0; i < 12; i++)
	{
		printf("xiao tao\n");
		arr[i] = 0;
	}
	return 0;
}

你觉得该代码有什么问题呢?

1.越界访问
2.死循环

第一个问题越界访问非常容易看出来,数组arr只有10个元素,下标从0-9,而循环12次,肯定越界访问了
每次都会打印一个xiao tao,并且把对应的arr[i]置为0。
所以最后答案应该就是打印了12次xiao tao,然后越界访问出现错误,使arr[10]=0,arr[11]=0了
但最后答案却不是这样。
答案变成了死循环了,死循环打印xiao tao

在这里插入图片描述

死循环的原因是什么呢?

这里涉及有关栈空间的知识:

1.
内存空间分为栈区,堆区和静态区

栈区一般存放局部变量,函数参数,函数返回值等
堆区是用来分配动态开辟的空间的
静态区是存放全局变量,static修饰的静态变量等

在这里插入图片描述


2.局部变量是在栈区存放的

3.栈区的使用习惯:
先使用高地址处的空间
再使用低地址处的空间
4.数组的地址随着下标的增长,地址是由低到高变化的

在这里插入图片描述
注意:
该测试是在VS2019 X86环境下进行,其他环境可能不一样,结果也就不一样,不能一概而论。
在变量i与数组之间一定有两个整形空间吗?
答案:不一定。
在VS2019 X86环境下,变量i与数组之间确实空了两个整形变量空间大小。
而在VC6.0环境下,变量i与数组之间没有剩余空间。
在gcc环境下,变量i与数组之间有一个整形空间大小
在这里插入图片描述

解决方法

可能有的人会这样想将变量i定义在数组的下面这样就不会发生死循环了
我们从栈空间使用方面来看,这样当然可以避免死循环,但是难道我们以后写数组都要把i写在数组的后面吗?
这样只能解决当前的问题,而不能解决根本。不过现在的编译器大多数会自己修改这个死循环问题,比如将变量的i的地址放在数组的下面,在release版本就是这样进行优化不会死循环。

我们一般可能想不到这样本质原因,但我们可以通过调试来解决这个问题
当让i不断的++,当i等于10时将arr[10]置0,当i等于11时将arr[11]置0,然后我们通过调试监视发现arr[12]与i的值相等,这时我们就要想到为什么会死循环了,arr[12]的地址就等于i的地址,将arr[12]修改成0,就等于将i改为0了。
在这里插入图片描述
将arr[12]置0,发现i也变成0了
在这里插入图片描述

总结

其实这道题是在特殊环境下才能实现的,但我们还是要注意的是其中的知识点:
1.栈区的使用习惯
先使用高地址的空间
再使用低地址的空间

2.数组随着下标的增长,地址不断增大

题目2:
在这里插入图片描述
本题来源于某公司面试题,与题1一模一样,都是会越界访问,发生死循环,本质上都是栈空间使用问题。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陶来咯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值