如何解决为什么全局和静态对象存储在bss部分中
我正在研究二进制文件的各个部分。我使用了下面的c ++代码:
// test.cpp
struct Test {
int i;
Test(int ii) : i(ii) {}
Test() {}
};
Test t0{5};
Test t1 = Test(5);
Test t2;
static Test t3;
static Test t4{5};
int i = 1;
int j;
static int k;
static int l = 1;
int main() {
return 0;
}
我使用命令g++ test.cpp
编译了此代码,并获得了名为a.out
的二进制文件。
然后,我使用命令objdump
提取bss
和data
的部分。
objdump -dj .data a.out
的输出:
a.out: file format elf64-x86-64
Disassembly of section .data:
0000000000201000 <__data_start>:
...
0000000000201008 <__dso_handle>:
201008: 08 10 20 00 00 00 00 00 .. .....
0000000000201010 <i>:
201010: 01 00 00 00 ....
0000000000201014 <_ZL1l>:
201014: 01 00 00 00 ....
objdump -dj .bss a.out
的输出:
a.out: file format elf64-x86-64
Disassembly of section .bss:
0000000000201018 <__bss_start>:
201018: 00 00 add %al,(%rax)
...
000000000020101c <t0>:
20101c: 00 00 00 00 ....
0000000000201020 <t1>:
201020: 00 00 00 00 ....
0000000000201024 <t2>:
201024: 00 00 00 00 ....
0000000000201028 <j>:
201028: 00 00 00 00 ....
000000000020102c <_ZStL8__ioinit>:
20102c: 00 00 00 00 ....
0000000000201030 <_ZL2t3>:
201030: 00 00 00 00 ....
0000000000201034 <_ZL2t4>:
201034: 00 00 00 00 ....
0000000000201038 <_ZL1k>:
...
因此,变量i
和l
由于已初始化,因此存储在.data
节中。变量j
和k
在.bss
部分中,因为它们尚未初始化。我能理解。
但是,为什么Test
的所有对象都在.bss
节中,即使这些对象已初始化?我认为t0
,t1
和t4
应该存储在.data
节中,但是显然我错了。
解决方法
.data
仅用于使用文字数据初始化的变量。
Test
对象是使用构造函数方法初始化的。因此,内存是在bss
中分配的,然后在启动期间调用构造函数以填充内容。
扩展公认的答案:有多种方法可以改变这种行为。很多地方已经讨论过了,例如: Guaranteeing static (constant) initialization of static objects
这是我的测试:
struct Test1 {
int a;
};
struct Test2 {
Test2(const int pa) : a(pa) {}
int a;
};
struct Test3 {
constexpr Test3(const int pa) : a(pa) {}
Test3(double d) : a((int)d) {}
int a;
};
struct Test4 {
int a {0x12345604};
};
Test1 s_test1 { 0x12345601 };//Object is placed directly in .data. No constructor executed.
Test2 s_test2 { 0x12345602 };//Object is placed .bss,initialization value is in .rodata and constructor is executed during initialization
Test3 s_test3_1 { 0x12345603 };//Object is placed directly in .data. No constructor executed.
Test3 s_test3_2 { 0.0 };//Object is placed .bss,init data is in .rodata and constructor is executed during initialization
Test4 s_test4;//Object is placed directly in .data. No constructor executed.
(我用 g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 和 arm-none-eabi-g++ (15:6.3.1+svn253039-1build1) 6.3.1 20170620)进行了验证
因此,如果您有一个非常大的静态对象,请确保通过 constexpr 构造函数对其进行初始化,以避免加倍内存消耗和缓慢的构造函数调用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。