当我尝试使数组溢出时gcc做了什么?

时间:2013-04-05 13:51:09

标签: c arrays gcc

我尝试了一段使数组溢出的代码,但是当我用gcc编译它时发生了意想不到的事情。以下是代码:

#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a[] = {0,2,4,7};
    int size = sizeof(a)/sizeof(int);
    int i;
    printf("%d, %X\n", size, &a);
    a[4] = 6;
    printf("%d, %X\n", size, &a);
    a[5] = 78;
    printf("%d, %X\n", size, &a);
    a[6] = 65;
    printf("%d, %X\n", size, &a);
    for (i = 0; i < size; i++) {
        printf("%d, ", a[i]);
    }
    printf("%d, %d, %d\n", a[size], a[size+1], a[size+2]);
    printf("\n");
    return 0;
}

结果是:

4, BFC4DDF8
6, BFC4DDF8
6, BFC4DDF8
6, BFC4DDF8
0, 2, 4, 7, 6, 5, 65, 0, 0

所以在代码中,我没有改变大小的值,但是当它运行时,它确实发生了变化!所以有人能告诉我为什么会这样吗?

PS:gcc版本是4.8.0。

根据@NPE的答案,我检查了size的地址,它实际上位于a之后的内存中。

但是当我添加一段代码时

printf("%X\n", &size);

printf("%d, %X\n", size, &a);

结果是

BFC39108
4, BFC3910C
4, BFC3910C
4, BFC3910C
4, BFC3910C
0, 2, 4, 7, 4, 78, 65

此时,size位于a之前的内存中。


事实上,无论我在哪里打印size的地址,它都位于a地址的正前方;如果我不打印size的地址,它就在a的地址后面。那么它仍然是编译器未定义的行为吗?

2 个答案:

答案 0 :(得分:4)

由于您在a结尾处写字,因此您的程序已undefined behaviour。这意味着它可以以任何方式表现,包括你观察的方式。

实践中发生的事情是size恰好位于a之后的内存中,以及下面的越界任务:

a[4] = 6;

覆盖size

请注意,如果您使用不同的编译器或不同的编译器设置,或者对程序进行看似无关紧要的更改,代码可能会以其他方式失败。或者它可以在整个测试过程中运行良好,然后在客户面前爆炸。

答案 1 :(得分:0)

你在a []数组的末尾覆盖了内存,因此覆盖了size的值。