You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

全局const POD类型是否需要执行静态初始化器?

静态初始化器疑惑:编译时常量为何出现在.init_array相关符号列表中

我正在尝试减少共享库中的静态初始化器以提升程序启动时间,核心思路是避免将拥有非平凡构造函数的对象设为静态对象。验证优化效果时遇到了一个问题:

测试程序

#include <iostream>

static const char foo[] = "1234567890";
static const std::string bar = "abcdefghij";

int main() {
    std::cout << foo << std::endl;
    std::cout << bar << std::endl;
}

检查结果

编译后用readelf查看符号表并关联.init_array段,发现foo和bar都出现在过滤结果里:

readelf -s .init_array ./a.out -W | egrep "foo|bar"
    11: 0000000000403010    11 OBJECT  LOCAL  DEFAULT   15 _ZL3foo
    12: 0000000000405200    32 OBJECT  LOCAL  DEFAULT   25 _ZL3bar

foo是编译时常量,按道理不需要静态初始化器,为什么会出现在这个结果里?


解答

你看到的是符号表的关联显示结果,而非foo真的存在于.init_array段中。

.init_array段存储的是程序启动时需要执行的初始化函数指针,readelf -s .init_array的作用是列出所有与.init_array段有符号关联的条目——但这并不意味着这些对象本身在.init_array里,只是它们的符号被工具关联展示了。

对于foo来说:

  • 它是编译期即可确定内容的字符数组,编译器会直接把它的内容放在只读数据段(通常是.rodata),完全不需要运行时初始化,自然不会有对应的初始化函数进入.init_array。
  • 之所以readelf结果里能看到它,是因为符号表中记录了该对象的信息,egrep过滤出了包含foo的行,和.init_array段本身没有直接关联。

真正需要静态初始化的是bar:

  • std::string拥有非平凡构造函数,编译器会生成对应的初始化函数,并将函数指针放入.init_array段,程序启动时会调用这个函数完成bar的构造。

你可以用更精准的命令验证:

# 直接查看.init_array段的十六进制内容
readelf -x .init_array ./a.out

这里只会看到bar对应的初始化函数地址,不会出现foo的相关内容。


内容的提问来源于stack exchange,提问作者Sathwik Matsa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 08:07:12