c++ - 为什么 GCC 将对全局实例的构造函数的调用放入不同的部分(取决于目标)?

标签 c++ gcc microcontroller ld linker-scripts

我有一些带有非空构造函数的全局实例的简单声明。这些构造函数在启动期间自动调用。我正在将 Linux 上的 C++ 交叉编译到不同的微 Controller 目标。


至于

  • arm-none-eabi-gcc-4.8.4
  • rx-elf-gcc-4.8-GNURX_v14.03 (GCC 4.8.3)

对构造函数的调用被放入 .init_array 部分。 map 文件如下所示:

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

.ctors 0x000000009d011508 0x4 libmotor.o

.ctors 0x000000009d01150c 0x4 libaudio.o


编译是用-ffunction-sections -fdata-sections完成的,链接器得到了--gc-sections

所有二进制文件都可以工作,但我想将所有调用放入同一部分(以简化链接描述文件的维护)。

  • 为什么有不同的目标部分?
  • 是否可以使用命令行选项更改默认部分?
  • 如果命令行选项不退出:是否可以在 GCC 编译时定义默认部分?

最佳答案

Bug 46770 - Replace .ctors/.dtors with .init_array/.fini_array on targets supporting them中有一个很长的讨论

我摘录了一些可以解释情况的项目:

为什么 .init_array 出现了?

  • We added .init_array/.fini_array in order to blend the SVR4 version of .init, which contained actual code, with the HP-UX version, which contained function pointers and used a DT_INIT_SZ entry in the dynamic array rather than prologue and epilogue pieces contributed from crt*.o files. The HP-UX version was seen as an improvement, but it wasn't compatible, so we renamed the sections and the dynamic table entries so that the two versions could live side-by-side and implementations could transition slowly from one to the other.

  • On HP-UX, we used .init/.init_array for static constructors, and they registered the corresponding static destructors on a special atexit list, rather than adding destructors to .fini_array, so that we could handle destructors on dlclose() events properly (subject to your interpretation of "properly" in that context)

.ctors.init_array 的执行顺序不同

Backwarding order of .ctors section

Some programs may implicitly rely on the fact that global constructors in archives linked later are run before constructors in the object linked against those archives. That is, given

g++ foo.o -lbar

where bar is a static archive, not a shared library, then currently the global constructors in objects pulled in from libbar.c will be executed before the global constructors in foo.o. That was an intentional choice because it is more likely to be correct than the reverse. However, the C++ standard does not guarantee it, so any programs which relies on this ordering is technically invalid.

.ctors的倒序问题

A lot of work was done in both GNU ld and gold to move constructors from .ctors to .init_array, all to improve startup latency for Firefox

Using .init_array/.fini_array instead of .ctors/.dtors removes the need for the associated (relative) relocations, and avoids the backwards disk seeks on startup (since while .ctors are processed backwards, .init_array is processed forward).

.ctors.init_array 的转换

The mainline versions of both GNU ld and gold now put .ctors sections into .init_array sections, and put .dtors sections into .fini_array sections.

评论:可能是在 GCC 4.7 中引入的。

ARM

ARM EABI has been using .init_array from day one.

评论:尽管如此,默认的链接描述文件包含一个 .ctors 输出部分。

GCC 配置

One option you have is to configure gcc with --disable-initfini-array.

评论:此选项不会出现在 mips-elf-gcc -v 的输出中(-v 显示“Configured with: ...”)。

关于c++ - 为什么 GCC 将对全局实例的构造函数的调用放入不同的部分(取决于目标)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28564078/

相关文章:

c++ - DirectX10 上的深度缓冲区不起作用

c++ - getline 跳过 char 数组的一个字符

c - 如何使这一动态位范围代码 GCC 兼容 64 位编译器?

并发访问结构成员

c - KEIL uVision 4问题

c++ - 如何 "disconnect"加速器、按键事件或鼠标按下事件在 GTK+ 小部件中?

c++ - 字符串文字中的递增字符

c++ - 使用查找表的可选帮助进行对象查找,如果未使用则必须优化掉

c - 如何在C中返回缓冲区地址

c++ - iMX31 依赖项?