首页 > 解决方案 > 在块范围内被覆盖的未初始化数组的值

问题描述

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {
    int send_buf[4];
    if(1){
        int hello[5]={1,2,3,4,5};        
    }
    for(int i=0; i<4; ++i)
        printf("%d ",send_buf[i]);
    printf("\n");
    return 0;
}

输出: 1 2 3 4

在执行上述 C 代码时,输​​出总是导致分配给hello块范围内的数组的值。send_buf但是,如果在打印 array 之前进行了任何引用(例如打印 的地址) send_buf,则输出会导致通常的不确定值。

有人可以解释为什么当内存已经在堆栈上分配send_buf时被覆盖的值?send_buf

是否是某种 GCC 编译器优化延迟分配未初始化的数组直到它被引用?

使用 GCC 版本 9.3.0 编译。

标签: arrayscgccinitializationcompiler-optimization

解决方案


当您不在 C 中(显式或隐式)初始化对象时,C 标准不保证它们具有任何固定值。它们的值可能会受到任何其他情况的影响,甚至可能会因每次使用而有所不同。

由于您没有初始化数组,编译器可能允许任何其他操作影响它。这可能包括允许 的定义hello影响出现在 中的值send_buf。可能起作用的一个事实是编译器会对值进行生命周期分析。例如,在如下代码中:

int p;
int q = 4;
printf("%d\n", q);
p = 3;
printf("%d\n", p);

编译器可能会看到,即使p在之前定义过q,也永远不会有一个“活”值与p中的值同时存在q,因此编译器可以使用与 相同的q内存p。类似地,编译器可能已经决定send_buf永远不会同时包含实时值hello,因此它可以使用与它相同的hello内存send_buf。然后,由于您从未将值放入 中send_buf,因此从中获取内存中的数据是hello您的程序的一种可能行为。

要吸取的一个教训是,在各种情况下出现在数组中的“奇怪”值是它可能没有被初始化的线索,补救方法是初始化它。


推荐阅读