全局变量似乎不占用任何内存空间

时间:2012-08-27 20:16:35

标签: c memory global-variables

我想准确理解全局变量在程序中的存储位置。在堆栈上?在堆上?在其他地方?

为此,我写了这个小代码:

int global_vector[1000000];
int main () {
    global_vector[0] = 1; // just to avoid a compilation warning
    while(true); // to give me time to check the amount of RAM used by my program
    return 0;
}

无论我制作多大global_vector,程序只使用非常少量的RAM。我不明白这个的原因。有人可以解释一下吗?

3 个答案:

答案 0 :(得分:11)

这完全取决于实现,但通常全局变量存储在与堆栈和堆分开的特殊内存段中。可以将此内存分配为可执行文件本身内部的固定大小缓冲区,也可以分配给操作系统启动时为程序提供的段。

您没有看到内存使用率上升的原因可能与操作系统处理虚拟内存的方式有关。作为优化,操作系统实际上不会为该巨型阵列提供任何内存,除非您实际使用它。尝试将程序更改为for循环遍历数组的整个内容,看看是否会导致RAM使用率上升。 (也有可能你的编译器中的优化器正在消除巨型数组,因为它几乎完全未使用。设置一个循环来读/写所有值也可能迫使编译器保留它)。

希望这有帮助!

答案 1 :(得分:5)

优化器可能完全删除了数组,因为你从不使用它。

答案 2 :(得分:4)

未给出显式初始值设定项的全局变量(在本例中与您的一样)默认情况下初始化为0。它们被放置在称为.bss segment的内存区域中,并且没有其他数据存储在目标文件/可执行文件中,指示数据的初始值(与显式初始化数据不同,后者必须存储其初始值某处)。

当OS加载程序时,它会读入所有段的描述并为其分配内存。因为它知道.bss段被初始化为全0,所以它可以做一个偷偷摸摸的技巧,以避免必须实际分配大量内存,然后将其初始化为全0:它为其分配地址空间进程页面表中的段,但所有页面都指向同一页面,填充为0。

该单个零页面也设置为只读。然后,如果进程写入.bss段中的某些数据,则会发生页面错误。操作系统拦截页面错误,找出正在发生的事情,然后实际为该页面数据分配唯一的内存。然后它重新启动指令,代码继续以其快乐的方式继续,就像内存一直被分配一样。

因此,最终结果是,如果你有一个零初始化的全局变量或数组,那么永远不会被写入的每个页面大小的数据块(通常为4 KB)实际上永远不会为它分配内存。

注意:我在这里用“已分配”这个词有点模糊。如果你深入研究这类事情,你可能会遇到诸如“保留”和“已提交”之类的词语。有关Windows上下文中这些术语的详细信息,请参阅this questionthis page