根据我的理解,未明确初始化的静态变量(以及GCC,即使设置了-fzero-initialized-in-bss
时明确初始化为零的静态变量,通常也会存储)在BSS部分。然而,当我尝试检查该行为时,这些变量似乎存储在通用数据部分中(使用初始化的全局变量)。如果我编译(使用-O0
进行测量)并运行:
#include <stdio.h>
#include <stdlib.h>
extern char etext, edata, end;
int i = 42;
int main(int argc, char* argv[])
{
static int j;
printf ("end of program (etext) = %10p\n",&etext);
printf ("end of initialized data (edata) = %10p\n",&end);
printf ("end of uninitialized data (end) = %10p\n",&end);
printf ("=====\n");
printf ("Value of i (initialized global) : %d\n",i);
printf ("Address of i : %10p\n",&i);
printf ("Value of j (static with no explicit initialization) : %d\n",j);
printf ("Address of i : %10p\n",&j);
return 0;
}
我得到了输出:
end of program (etext) = 0x40067d
end of initialized data (edata) = 0x600af0
end of uninitialized data (end) = 0x600af0
=====
Value of i (initialized global) : 42
Address of i : 0x600ae0
Value of j (static with no explicit initialization) : 0
Address of i : 0x600ae8
因此i
和j
存储在&etext
和&edata
之间的连续内存地址,这是常规数据部分。此外,似乎&edata == &end
如果我理解正确,则意味着BSS是空的。
现在我意识到编译器放置哪个变量是一个实现选择,它产生的结果是正确的。但我只是想知道为什么我会得到这种行为,如果有办法告诉gcc明确地将这些变量放在BSS中(我在手册中没有看到任何明显的解决方案)。
答案 0 :(得分:3)
您的代码中有错误。你为edata和end打印end
的地址,所以当然你假设edata == end,它们不是。
当我修复代码并运行它时,我得到:
程序结束(etext)= 0x8048578
初始化数据结束(edata)= 0x804988c
未初始化数据的结尾(结束)= 0x8049894i的值(初始化全局):42
地址:i:0x8049888
j的值(没有显式初始化的静态):0
地址j:0x8049890
很清楚j
位于edata和end之间的区域,与i
不在同一个地方。
(gcc 5.2.1 20150911(Debian 5.2.1-17),32bit)
答案 1 :(得分:1)
可执行映像中的BSS只是一个数字,表示在未初始化变量加载时要保留多少字节。通过这种方式,对于许多未初始化的变量,图像不会变得非常大。当数字很小时,例如在你的例子中,几乎没有任何保存和开销,编译器可能已经决定将它们全部放在DATA段中。