为什么GCC将对全局实例构造函数的调用放在不同的部分(取决于目标)
Why does GCC put calls to constructors of global instances into different sections (depending on the target)?
我有一些带有非空构造函数的全局实例的简单声明。这些构造函数在启动期间自动调用。我在Linux上交叉编译C++到不同的微控制器目标。
对于
- 臂-酮-eabi-gcc-4.8.4
- rx-elf-gcc-4.8-GNURX_v14.03(通用条款4.8.3)
对构造函数的调用被放入CCD_ 1部分。地图文件如下所示:
.init_array 0x00007cb8 0x4 libmotor.o
.init_array 0x00007cbc 0x4 libaudio.o
对于
- mips-elf-gcc-4.8.2
- avr-gcc-4.8.1
- msp430-gcc-4.6.3
这些呼叫进入.ctors
部分:
.cctors 0x000000009d011508 0x4 libmotor.o
.ctors 0x000000009d01150c 0x4 libaudio.o
用-ffunction-sections -fdata-sections
进行编译,得到--gc-sections
。
所有二进制文件都可以工作,但我希望将所有调用放在同一部分(以简化链接器脚本的维护)。
- 为什么有不同的目标部分
- 是否可以使用命令行选项更改默认部分
- 如果命令行选项没有退出:是否可以在GCC编译时定义默认部分
Bug 46770中有一个很长的讨论-在支持的目标上用.init_array/.fini_array替换.ectors/.dtors
我提取了一些项目来解释这种情况:
为什么会出现.init_array
我们添加了
.init_array
/.fini_array
,以便将包含实际代码的.init
的SVR4版本与包含函数指针并在动态数组中使用DT_INIT_SZ
条目的HP-UX版本混合在一起,而不是由crt*.o文件提供的序言和尾声部分。HP-UX版本被认为是一种改进,但它不兼容,所以我们重命名了部分和动态表条目,以便这两个版本可以并行运行,并且实现可以缓慢地从一个过渡到另一个。在HP-UX上,我们使用
.init_array
0/.init_array
作为静态构造函数,它们在一个特殊的atexit
列表中注册了相应的静态析构函数,而不是将析构函数添加到.fini_array
中,这样我们就可以正确地处理dlclose()
事件上的析构函数(根据您在该上下文中对"正确"的解释)
.ctors
和.init_array
的执行顺序不同
.ctors
段回水顺序一些项目可能隐含地依赖于这样一个事实:稍后链接的存档中的构造函数在链接到这些档案的对象。也就是说,给定
g++ foo.o -lbar
其中bar是静态存档,而不是共享库,则当前将执行从libbar.c拉入的对象中的全局构造函数在foo.o中的全局构造函数之前。这是一个有意的选择因为它更有可能是正确的,而不是相反的。然而C++标准不能保证它,所以任何依赖它的程序订购在技术上是无效的。
.ctors
的退单问题
GNU
ld
和gold
都做了大量工作,将构造函数从.ctors
移动到.init_array
,所有这些都是为了改善Firefox 的启动延迟使用
.init_array
/.fini_array
而不是.ctors
/.dtors
消除了对相关(相对)重新定位的需要,并避免了启动时的向后磁盘查找(因为当.ctors
向后处理时,.init_array
向前处理)。
从.ctors
到.init_array
的转换
GNU
ld
和gold
的主线版本现在将.ctors
节放入.init_array
节,将.dtors
节放入.fini_array
节。
评论:可能与GCC 4.7一起引入。
ARM
ARM EABI从第一天起就一直在使用
.init_array
。
注释:尽管如此,默认的链接器脚本包含一个.ctors
输出部分。
GCC配置
您可以选择使用--disable initfini数组配置gcc。
注释:此选项不会出现在mips-elf-gcc -v
的输出中(-v
显示"Configured with:…")。
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- C++A*算法并不总是在路径中具有目标节点
- 基于树莓pi的tensorflow lite量化ssd目标检测
- 为测试目标创建具有不同源文件夹的文件
- 重载运算符new[]的行为取决于析构函数
- 使用源向量作为目标
- 是否可以用C++/WinRT将windows 10.0.14393作为目标
- 在 CMake 中为每个目标设置编译器/链接器标志
- qmake:检测目标位宽(32 位或 64 位)
- 如何在 CMake 中对目标依赖项进行分组?
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- 如何为包含头文件的目标编写生成文件?
- 线性优化目标函数中的绝对值
- 新的放置取决于 iostream
- Writefile() 无法写入数据,具体取决于数据的长度
- memcpy是否取决于源指针和目标指针的类型
- CMAKE - 如何定义目标库的符号,具体取决于谁使用它
- 如何使目标取决于特定的文件名
- 为什么GCC将对全局实例构造函数的调用放在不同的部分(取决于目标)
- 取决于CMake外部项目的INSTALL目标