讨论一个堆栈越界的问题

我们先看一个linux下的C代码,分析一下运行结果:

1 int main(int argc, char* argv[]) {
2     int i = 0;
3     int arr[3] = {0};
4     for(; i<=3; i++) {
5         arr[i] = 0;
6         printf("hello world\n");
7     }
8     return 0;
9 }​

显然,由于数组越界导致行为未知?
其实,行为虽然非法,但并不是未知或者因为非法访问而退出。

我们知道,在 C 语言中,只要不是访问受限的内存,所有的内存空间都是可以自由访问的。根据数组寻址方式(线性连续),a[3] 也会被定位到某块不属于数组的内存地址上,而这个地址正好是存储变量 i 的内存地址,那么 a[3]=0 就相当于 i=0,所以就会导致代码无限循环。

看到这里,应该还有很多疑问,但是还是请先思考一下。

我们再进一步,函数体内的局部变量存在栈上,且是连续压栈。在Linux进程的内存布局中,栈区在高地址空间,从高向低增长。变量 i 和 arr 在相邻地址,且 i 比 arr 的地址大,所以 arr 越界正好访问到 i。当然,前提是 i 和 arr 元素同类型,否则那段代码仍是未决行为。

看到这里,应该大体的原因已经说清楚了,那么如果想了解的更加深入,我给大家推荐一个链接:GCC 中的编译器堆栈保护技术
最后,给大家再留一个思考:如果 arr[3] 变成 arr[5],结果是否还会无限循环呢?

图片描述

阅读 1k

推荐阅读
聊聊架构
用户专栏

原创、收集、整理互联网架构技术文章

5 人关注
19 篇文章
专栏主页