为什么全局和静态对象存储在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提取bssdata的部分。

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>:
        ...

因此,变量il由于已初始化,因此存储在.data节中。变量jk.bss部分中,因为它们尚未初始化。我能理解。

但是,为什么Test的所有对象都在.bss节中,即使这些对象已初始化?我认为t0t1t4应该存储在.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 构造函数对其进行初始化,以避免加倍内存消耗和缓慢的构造函数调用。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...