一段神奇的c代码错误分析
程序员文章站
2022-07-15 15:26:52
...
源代码
#include <stdio.h>
int main(int argc, char* argv[])
{
int i = 0;
int arr[3] = {0};
printf("first i is %p\n", &i);
printf("first arr loc is %p\n", &arr);
for (; i < 3; i++)
{
printf("arr %d loc is %p\n", i, &arr[i]);
printf("i:%d loc is %p\n", i, &i);
arr[i] = 0;
printf("hello world\n");
}
return 0;
}
输出
在centos7 的机器上编译然后输出得到
first i is 0x7ffd1a10d21c
first arr loc is 0x7ffd1a10d210
arr 0 loc is 0x7ffd1a10d210
i:0 loc is 0x7ffd1a10d21c
hello world
arr 1 loc is 0x7ffd1a10d214
i:1 loc is 0x7ffd1a10d21c
hello world
arr 2 loc is 0x7ffd1a10d218
i:2 loc is 0x7ffd1a10d21c
hello world
神奇的地方来了
将
for (; i < 3; i++)
改成
for (; i <= 3; i++)
现在再编译输出会无限循环输出,截取其中的一段得到:
first i is 0x7ffd1a10d21c
first arr loc is 0x7ffd1a10d210
arr 0 loc is 0x7ffd1a10d210
i:0 loc is 0x7ffd1a10d21c
hello world
arr 1 loc is 0x7fff75ecb214
i:1 loc is 0x7fff75ecb21c
hello world
arr 2 loc is 0x7fff75ecb218
i:2 loc is 0x7fff75ecb21c
hello world
arr 3 loc is 0x7fff75ecb21c
i:3 loc is 0x7fff75ecb21c
hello world
arr 1 loc is 0x7fff75ecb214
i:1 loc is 0x7fff75ecb21c
hello world
arr 2 loc is 0x7fff75ecb218
i:2 loc is 0x7fff75ecb21c
hello world
arr 3 loc is 0x7fff75ecb21c
i:3 loc is 0x7fff75ecb21c
.....
为什么会发生这种现象呢?
究其原因是因为
函数体内的局部变量是存在栈上的,且是连续压栈。在Linux进程的内存布局中,栈区在高地址空间,从高向低增长。变量i和arr在相邻的地址,其i比arr的地址大,由于我们只声明数组大小为3,所以如果访问arr[3]其实已经越界了,但是虽然arr[3]是不存在的,但是如果越界访问的话我们可以发现他的地址是0x7fff75ecb21c
,这和其实就是i
的地址。
所以:
arr[3] = 0;
其实就是
i = 0
所以会一直进入死循环的情况。
上一篇: HASH表
下一篇: 一段输出明清皇帝年号的代码