理解C中数据bss段的大小命令

我得到size命令意外的输出。

Afaik初始化存储在data段中的全局和静态variables,并初始化为存储在bss段中的0个全局/静态variables。

printf("%d",sizeof(int)); 给出int大小4.但是, bssdata段不相应增加到4。

 #include <stdio.h> int main() { return 0; } C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe text data bss dec hex filename 10044 2292 2512 14848 3a00 memory-layout.exe #include <stdio.h> int g; //uninitialised global variable so, stored in bss segment int main() { return 0; } C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe text data bss dec hex filename 10044 2292 2528 14864 3a10 memory-layout.exe 

为什么bss增加了16(2528 – 2512)而不是4? (在上面的代码中)

 #include <stdio.h> int g=0; //initialised to 0 so, stored in bss segment int main() { return 0; } C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe text data bss dec hex filename 10044 2292 2512 14848 3a00 memory-layout.exe 

尽pipe使用全局variables,但在bss中没有增加。 为什么?

  #include <stdio.h> int main() { static int g; //should be on bss segment return 0; } C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.ex text data bss dec hex filename 10044 2292 2512 14848 3a00 memory-layout.exe 

尽pipe使用静态variables,为什么在bss段没有增加?

我还有一个问题,这里代表什么?

首先要考虑的是内存对齐。 变量和部分可以填充,使他们坐在地址边界。 在第二个例子中,你会看到从第一个增加16,这表明填充16字节的边界(2512/16 = 157,2528/16 = 158)。 这完全取决于实施。

就C而言,第二个例子与第三个例子不同,因为编译器无法知道int g是一个定义还是只是另一个文件中定义的整数的声明(可能是任何值)。 它留下了链接器处理的引用,而这可能会导致填充差异。

在第三个例子中, g被明确定义并设置为0,所以编译器知道把它放在BSS部分。

可以用我的系统生成的程序集来证明这一点:

int g (在这种情况下没有定义BSS部分)

 .comm g,4,4 

这是链接器处理符号的指令,因为编译器不能完全确定如何处理它。

int g = 0

  .bss .align 4 .type g, @object .size g, 4 g: .zero 4 

在这里,编译器确切地知道该做什么,因此为符号定义了BSS部分。

在我的情况下,链接器解决这些相同的。 两者都放在同一地址的BSS部分,因此BSS大小没有差别。 你可以用nm这样的工具来检查布局。

 nm -n file2 file3 | grep g$ 000000000060103c B g 000000000060103c B g 

即在这个系统上g是在相同的地址。 或者,使用调试器:

 (gdb) info symbol 0x60103c g in section .bss of /tmp/file2 

还要注意,在最后的例子中,变量可以被优化,因为它具有内部连接。

至于dec ,它只是十进制小节的总和。

这是来自linux上的gcc:

 No Variable text data bss dec hex filename 915 248 8 1171 493 none.out Uninitialized Global text data bss dec hex filename 915 248 12 1175 497 u_g.out Initialized Global to 123 text data bss dec hex filename 915 252 8 1175 497 i_g.out Initialized Local to 124 text data bss dec hex filename 915 252 8 1175 497 i_l.out Initialized Global to 0 text data bss dec hex filename 915 248 12 1175 497 i_g_0.out Initialized Local to 0 text data bss dec hex filename 915 248 12 1175 497 i_l_0.out 

这是从Windows上的mingw64开始的:

 No Variable text data bss dec hex filename 3173 1976 448 5597 15dd none.out Uninitialized Global text data bss dec hex filename 3173 1976 464 5613 15ed u_g.out Initialized Global to 123 text data bss dec hex filename 3173 1976 448 5597 15dd i_g.out Initialized Local to 124 text data bss dec hex filename 3173 1976 448 5597 15dd i_l.out Initialized Global to 0 text data bss dec hex filename 3173 1976 480 5629 15fd i_g_0.out Initialized Local to 0 text data bss dec hex filename 3173 1976 480 5629 15fd i_l_0.out 

因此,虽然我没有问题的最终答案(不适合注释),但是结果让我怀疑Windows和/或MinGW(即不是gcc)的可执行文件格式。

BSS只包含未明确初始化的静态和全局值。 即使你明确地初始化它,如果它没有显式初始化,它将被初始化为相同的值,显式初始化的事实意味着它不属于bss。