.bss节大小与对象/可执行文件大小

时间:2017-02-14 06:49:28

标签: c++ c gcc g++

如果我有一个像

这样的C或CPP程序
#include <stdio.h>
int bss_section_object[10];
int main()
{
    return 0;
}

用gcc / g ++编译代码后,

$g++ -save-temps aa.cpp

如果我检查生成的对象和可执行文件的大小

$ls -ltr
-rw-rw-r-- 1 dinesh dinesh    77 Feb 14 12:42 aa.cpp
-rw-rw-r-- 1 dinesh dinesh 17283 Feb 14 12:45 aa.ii
-rw-rw-r-- 1 dinesh dinesh   517 Feb 14 12:45 aa.s
-rw-rw-r-- 1 dinesh dinesh  1296 Feb 14 12:45 aa.o
-rwxrwxr-x 1 dinesh dinesh  8592 Feb 14 12:45 a.out
$size a.out
   text    data     bss     dec     hex filename
   1099     544      72    1715     6b3 a.out
$size aa.o
   text    data     bss     dec     hex filename
     67       0      40     107      6b aa.o

现在,如果我评论在.bss部分

上创建的对象
#include <stdio.h>
//int bss_section_object[10];
int main()
{
    return 0;
}

并在编译后检查尺寸: -

$ls -ltr
-rw-rw-r-- 1 dinesh dinesh    79 Feb 14 12:46 aa.cpp
-rw-rw-r-- 1 dinesh dinesh 17256 Feb 14 12:46 aa.ii
-rw-rw-r-- 1 dinesh dinesh   378 Feb 14 12:46 aa.s
-rw-rw-r-- 1 dinesh dinesh  1232 Feb 14 12:46 aa.o
-rwxrwxr-x 1 dinesh dinesh  8552 Feb 14 12:46 a.out
$size a.out
   text    data     bss     dec     hex filename
   1099     544       8    1651     673 a.out
$size aa.o
   text    data     bss     dec     hex filename
     67       0       0      67      43 aa.o

我可以看到它们的大小因“bss_section_object”大小而异。

如果我阅读.bss部分的详细信息,那么根据维基百科: - “BSS在运行时需要的大小记录在目标文件中,  但BSS(与数据段不同)不占用任何实际空间  对象文件“。 我们可以在其他计算机科学中看到类似的.bss部分描述 书籍也是如此。

现在,如果.bss部分没有占用目标文件中的任何空间,那么为什么 对象的大小以及基于大小的可执行文件更改 在.bss部分创建的对象?

有人可以解释一下它的细节吗?

1 个答案:

答案 0 :(得分:2)

当你说:

时,你是完全正确的
  

“BSS在运行时需要的大小记录在目标文件中,但BSS(与数据段不同)不会占用目标文件中的任何实际空间”

因为未初始化的数据放在程序的.bss部分中,其类型为SHT_NOBITS(请参阅elf(5) manpage)。 为了说服自己此部分不占用ELF文件中的任何空格,请尝试readelf -Wl /bin/ls并查看第四部分:

[...]
LOAD 0x01a310 0x000000000061a310 0x000000000061a310 0x0012f0 0x002010 RW  0x200000
[...]
`03  .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss

您可以看到它包含(其中包括).bss部分,文件大小为0x12f0,但内存大小为0x2010。区别在于.bss部分的大小。

此部分未包含在文件中,因为在程序启动时关联的内存区域将被清零,并且不必在文件中存储零。

你是对的,但你的测试是错误的

在您给出的示例中,假设您禁用了优化和调试器符号,您在文件大小中看到的差异可能由符号表解释,而不是.bss部分大小的更改。

以下是您可以重现的实验:

you$ cat main.cpp
#include <stdio.h>
#ifdef USE_BSS
int bss_section_object[10];
#endif
int main()
{
    return 0;
}
you$ g++ -O0 main.cpp -o without.elf
you$ g++ -DUSE_BSS -O0 main.cpp -o with.elf
you$ ls -l *.elf
-rwxr-xr-x. 1 you you 8505 Feb 14 10:00 with.elf
-rwxr-xr-x. 1 you you 8462 Feb 14 10:00 without.elf

此时,您可能认为更改.bss段大小会影响文件大小,但实际上差异是由于符号表中的附加符号bss_section_object(您可以使用{删除它) {1}}):

strip command

耶!通过删除符号表部分you$ readelf -WS with.elf > with && readelf -WS without.elf > without you$ diff with without 30c30 < [25] .bss NOBITS 0000000000601040 00102c 000048 00 WA 0 0 32 --- > [25] .bss NOBITS 000000000060102c 00102c 000004 00 WA 0 0 4 33,34c33,34 < [28] .symtab SYMTAB 0000000000000000 0018e8 000618 18 29 45 8 < [29] .strtab STRTAB 0000000000000000 001f00 000239 00 0 0 1 --- > [28] .symtab SYMTAB 0000000000000000 0018e8 000600 18 29 45 8 > [29] .strtab STRTAB 0000000000000000 001ee8 000226 00 0 0 1 # Yep, the .symtab and .strtab are also different you$ strip *.elf you$ ls -l *.elf -rwxr-xr-x. 1 you you 6232 Feb 14 10:06 with.elf -rwxr-xr-x. 1 you you 6232 Feb 14 10:06 without.elf (它与关联的字符串表.symtab),您最终会得到相同的文件大小,但不同的.strtab部分大小,这正是您所期望的。< / p>