绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
C语言数组越界导致无限循环
2019-11-07 19:06:35

昨天晚上,我正在给之前获奖的同学发奖品,正在进行中的时候,看到黄兄推送了一篇文章,里面讲到数组越界会导致无限循环。

关于抽奖看这篇文章《Linux进程管理数据结构》,以后也会不定期抽奖,今年多赚点钱,过年的时候,希望给大家抽一个大奖,喜欢的读者使劲给转发点赞,关注,未来是你们的,大奖也是你们的,感谢支持,不喜欢的请轻拍。过年抽奖我还是很期待的,每年公司的年会抽奖的时候,我总是能小中一把,有一年我还中了个一等奖,不知道大家对一等奖什么概念,中一等奖的概率非常低,集人品运气于一身的,我当时酝酿了全宇宙的力量,不说了,发功的时候真的非常累。

就是这个截图,我看了下,感觉有点意思,赶紧就自己敲下代码看看是怎么回事,可惜的是,我怎么也没看到出现无限循环啊。

代码如下:

#include "stdio.h"

int main()
{
	int a[10] , i;
	
	for(i = 1;i<= 10;i++){
		a[i] = 0;
		printf("%d %d\n",i,a[i]);
	}	
	
	return 0;
}

我先是在 dev c++ 上面试了下,结果如下


我这时候想,黄兄是不是忽悠我了,我要去成都叫他请我吃饭,然后我就给他评论

评论如下


竟然还有人给我的评论点赞了,啊啊啊啊啊啊~

不死心,赶紧又到Linux 下用 gcc编译 结果如下


还是没有无线循环,我要死了,要是在群里面讨论这个,我要是说不出来会不会丢脸一个晚上。

赶紧用大招,看看i的地址和a[i] 的地址

看这个图,i等于 10的时候, &a[10] 的地址和 i的地址还是独立的,虽然 a[10]已经超过了 数组的范围,但是并没有对i造成任何影响。

然后,我脑子一响,突然顿悟发现这个代码的问题所在了,这个数组越界没有越过去,要是越过去了,侵犯了i的领土「内存地址」了肯定就死循环了。

代码修改一下

#include "stdio.h"

int main()
{
	int a[10] , i;
	
	for(i = 1;i<= 12;i++){
		a[i] = 0;
		printf("%d %d\n",i,a[i]);
	}	
	
	return 0;
}

看看内存分布

上图中 i = 10的时候,&a[10] 还没有越界到 &i「i的地址」,等下一次循环 i = 11的时候,那 &a[11] 就等于 &i 了,a[11] = 0,其实也就是 i= 0,死循环也就是这样来了。

从这个例子我们可以明白一点,为什么数组不能越界操作了没?如果真的是项目里面的代码,要是编译器也不给出提示,那么你即将构造一个非常难排查的bug出来。

如果对上面的地址还是不感冒,可以看看这个图片



a我们定义的是10的大小,但是我们使用 a[10],这个是越界操作,越界操作编译器不会提示编译出错,但是这样操作就可能侵犯到i的地址,实际上把i给赋值了,所以会导致i=0,一直跳不出for循环。

我们正常一个数组遍历会这样写

#include "stdio.h"

int main()
{
	int i;
	int a[10];
	
	for(i = 0;i < sizeof(a)/sizeof(a[0]);i++){
		a[i] = 0;
		printf("%d %d %p %p\n",i,a[i],&i,&a[i]);
	}	
	
	return 0;
}

编译器就好像法律,约束着人们的行为,但是有些法律没有涉及到的,就很容易被打擦边球。

后用这个代码看看内存的增长「一个读者奉献的」

#include <stdio.h>

int main(void)
{
	#pragma pack (4)
	int j;
	int a[10];
	int i;
	#pragma pack()

	printf("a=%p &a[10]=%p &i=%p &a[-1]=%p &a[-2]=%p &j=%p\r\n",a, &a[10],&i,&a[-1],&a[-2],&j);
	
	return 0;
}


分享好友

分享这个小栈给你的朋友们,一起进步吧。

Linux技术精选专区
创建时间:2020-07-08 10:30:23
Linux,全称GNU/Linux,是一套免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年次释出,它主要受到Minix和Unix思想的启发,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • dapan
    专家
戳我,来吐槽~