如何解决为什么在这些不同情况下数据/ BSS大小会发生变化?
我正在学习虚拟内存管理和进程的内存分配。并做一些实验。有一些令人困惑的地方,如下所示:
案例1
#include <iostream>
int main() {
return 0;
}
编译代码并使用二进制文件运行size
并得到以下输出:
text data bss dec hex filename
1985 640 8 2633 a49 main
案例2: 将代码更改为:
#include <iostream>
int global;
int main() {
return 0;
}
并重建它,大小输出为:
text data bss dec hex filename
1985 640 16 2641 a51 main
注意:data
的存储部分未更改,但是bss
从8
更改为16
。 这个结果对我来说很有意义,因为int global
定义了一个未初始化的全局变量。
案例3: 然后将代码更改为:
#include <iostream>
int global = 5;
int main() {
return 0;
}
我初始化了全局变量。然后再次分析二进制文件:
text data bss dec hex filename
1985 644 4 2633 a49 main
这一次,更改对我而言没有意义。与case1相比,为什么data
部分增加了4个字节,而bss
部分减少了4?
解决方法
差异由链接器及其决定布局二进制文件的方式引起。 x86(GNU ld
)上的G ++默认链接器。
要了解差异,让我们以三种不同的方式来编译测试用例:
$ for x in *.cpp ; do g++ -g3 $x -o $x.ld.exe ; done # GNU ld
$ for x in *.cpp ; do g++ -g3 $x -o $x.gold.exe -fuse-ld=gold ; done # gold
$ for x in *.cpp ; do g++ -g3 $x -o $x.gold.exe -fuse-ld=lld ; done # lld
现在,大小如下:
text data bss dec hex filename
1873 656 8 2537 9e9 test1.cpp.ld.exe
1873 656 16 2545 9f1 test2.cpp.ld.exe
1873 660 4 2537 9e9 test3.cpp.ld.exe
text data bss dec hex filename
1877 656 2 2535 9e7 test1.cpp.gold.exe
1877 656 9 2542 9ee test2.cpp.gold.exe
1877 660 2 2539 9eb test3.cpp.gold.exe
text data bss dec hex filename
1817 576 2 2395 95b test1.cpp.lld.exe
1817 576 9 2402 962 test2.cpp.lld.exe
1817 580 2 2399 95f test3.cpp.lld.exe
bss
部分的行为可以解释如下:
这里要存储两个或三个变量(completed.0
,可能是global
和std::__ioinit
)。始终存在的两个大小和对齐方式各为1个字节。仅在情况2中存在的全局变量的大小和对齐方式为4个字节。这就是为什么在情况1和情况3中gold
和lld
都需要bss
段使用2个字节的原因。对于情况2,global
的存储格式是这两个单字节值,在第一个1字节值和global
之间需要额外的3个字节填充。
通常来说,GNU ld
的功能类似,只是它使用bss
部分来提供部分间的填充。在情况1和3中,实际上仅使用bss
节的2个字节,而情况2使用bss
节的9个字节。由于在情况3中data
增加了4个字节,并且bss
在data
之后进行了布局,因此删除了其中的4个填充字节,以使后续节的偏移保持对齐。这也是为什么在引入bss
时global
节的大小增加8个字节而不是4个字节的原因:GNU ld
确保该节的末尾保持8个字节对齐。>
更短的版本是:.bss
节通过写时复制被映射到零页-任何未明确初始化的 变量都将添加到{{1 }},它实际上并不存在于ELF 文件中,仅在更改其变量之一的内容时才会分配(我简化了,分配是按页进行的,因此对此有更多详细信息。)
为它提供默认值时,不能将其映射到零页:它的值必须存在于ELF文件本身中,并映射到内存中(同样,写时复制,因此如果然后您更改值,将为新页面分配变量的修改值。如果将其更改为.bss
,它将被添加到const int global = 5;
中,并且您会看到.rodata
的大小增加了。
我过去曾在博客中介绍过.text
命令:https://flameeyes.blog/2008/12/01/for-elves-size-matters/
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。