C语言数组越界导致死循环实例解析

起因是今早在朋友圈看到一位朋友问出了这样的问题:
C语言数组越界导致死循环实例解析_第1张图片
朋友圈居然有人问技术问题,勾起了我的兴趣 : )

一、理论分析

C语言数组越界导致死循环实例解析_第2张图片
首先很明显这是段C语言代码,如果是Java编译都不会通过,数组越界也会抛出异常。第一眼看上去我觉得是a[10]数组越界导致i的值被改成了0,导致了死循环。

但我试了下这段代码并没有复现死循环。然后我回忆了在C语言中,数组a和变量i都分配在内存中的栈区。由于栈区是由高地址向低地址增长,所以a[0]的地址高于i的地址。而数组内部元素的地址是递增的,所以x取任意非负整数,a[x]的地址始终大于i的地址。修改a[x]就无法改变i的值,也无法造成死循环。

二、修改代码复现死循环

#include 

int main()
{
	// 调换定义位置
    int i,a[10];
    for (i = 0; i <= 10; i++)
    {
        a[i] = 0;
        printf("a[%d]-add=%d i-add=%d\n",i, &a[i], &i);
    }
    return 0;
}

既然栈中先定义的变量地址高于后定义的变量地址,那我们可以将i和a的定义调换位置,这样a[0]的地址小于i的地址,a[x]的地址大于a[0]的地址,也就可能等于i的地址。运行结果打印出地址方便观察:

a[0]-add=6422000 i-add=6422044
a[1]-add=6422004 i-add=6422044
a[2]-add=6422008 i-add=6422044
a[3]-add=6422012 i-add=6422044
a[4]-add=6422016 i-add=6422044
a[5]-add=6422020 i-add=6422044
a[6]-add=6422024 i-add=6422044
a[7]-add=6422028 i-add=6422044
a[8]-add=6422032 i-add=6422044
a[9]-add=6422036 i-add=6422044
a[10]-add=6422040 i-add=6422044

我们可以看到调换位置后a[10]的地址也不等于i的地址,两者之间还差了4 byte,数组a和变量i间存在4byte的空隙,即a[11]的地址等于i的地址。将i <= 10改为i <= 11成功复现死循环。

另外还有一个知识点,程序运行多次,i的地址始终为6422044不会变动,这是因为6422044是变量i的虚拟地址,不是真实的物理地址。这个地址不受其他程序的影响,只收这个程序本身影响。

你可能感兴趣的:(操作系统,C++,c语言,开发语言)