如果我有一个像
这样的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部分创建的对象?
有人可以解释一下它的细节吗?
答案 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>