默认情况下为什么BSS段是“16”?

4
据我所知,C语言程序的分段是这样的:
        High address
|---------------------------|
|env/cmd line args vars     |
|---------------------------|
|      stack segment        |--> uninitialized auto vars
|---------------------------|
|---------------------------|
|---------------------------|
|      heap segment         |--> dynamic allocated memory
|---------------------------|
|      BSS segment          |--> uninitialized static/global vars
|---------------------------|
|      data segment         |--> initialized static/global vars
|---------------------------|
|      text segment         |--> initialized auto vars/exec instructions
|---------------------------|
        Low address

在我的RHEL 5.4 64位机器上,对于以下C程序:
#include <stdio.h>
int main()
{
}

当我执行以下操作时:
# size a.out
   text    data     bss     dec     hex filename
   1259     540      16    1815     717 a.out

我不理解为什么会出现bss=16,因为我没有声明或初始化任何全局/静态变量。
1个回答

2

在Windows上使用gcc编译更糟糕:

main.c:

#include <stdio.h>

int main( int argc, char* argv[] )
{
    return 0;
}

编译:

C:\>gcc main.c

大小:

C:\>size a.exe
   text    data     bss     dec     hex filename
   6936    1580    1004    9520    2530 a.exe

bss包含整个链接的可执行文件,在这种情况下,链接了使用静态C初始化的各种库。

在Windows上使用-nostartfiles选项可以获得更好的结果。您也可以尝试使用-nostdlib和-nodefaultlibs选项。

编译:

C:\>gcc -nostartfiles main.c

大小:

C:\>size a.exe
   text    data     bss     dec     hex filename
    488     156      32     676     2a4 a.exe

移除所有库(包括c库),你将得到一个“可执行文件”,它包含您编译的内容,并且bss大小为0:

main.c:

#include <stdio.h>

int _main( int argc, char* argv[] )
{
    return 0;
}

编译:
C:\>gcc -nostartfiles -nostdlib -nodefaultlibs main.c

大小:

C:\>size a.exe
   text    data     bss     dec     hex filename
     28      20       0      48      30 a.exe

可执行文件无法运行!


你的意思是说C库中有全局/静态变量声明,对吗? - DragonX
1
不一定是C库,而是各种支持库,以获得适用于您的操作系统的可执行文件。在Windows上,有很多垃圾代码需要添加到main()中,以使其成为一个工作应用程序。值得在系统上查看objdump -S ./a.out输出,以了解应该是简单代码周围有多少代码。您的理解是正确的,只是编译器“悄悄地”添加了支持库。 - Brian Sidebotham
1
@DragonX 值得一提的是,执行 gcc -v main.c 并检查最终的链接步骤,以查看系统链接了哪些库。在我的 Windows 系统下,它是 -lmingw32 -lgcc_eh -lgcc -lmoldname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc_eh -lgcc -lmoldname -lmingwex -lmsvcrt c:/.../crtend.o 链接了相当多的库,尽管大多数都是 DLL。 - Brian Sidebotham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接