将静态对象放在一起的标准方法

standard way to put static objects together

我想将一些具有静态链接的对象放在一起,而不交错任何其他数据。这些对象在单独的源文件中定义。顺序无关紧要,只要它们是连续的(minimal/standard 填充除外)。

在 gcc 中,我可以使用 __attribute__((section("mydata"))) 实现这一点,但是 AFAIK 这是 GCC 特定的,只有许多编译器支持它(gcc、llvm 和其他一些,但我认为不msvc),针对很多目标(精灵是的,其他我不确定,我怀疑)。

Q1:有没有标准的方法来实现这个?

Q2:GCC是否保证对象与填充是连续的?即可以通过具有恒定步幅的线性扫描来枚举对象。

问题 3:GCC 和其他支持该属性的编译器在行为上有区别吗?

问题 4:哪些目标和主要编译器不支持这个?

听起来您正在尝试生成独立于平台的代码(因此需要一种标准机制)并且虽然您可以访问源代码,但您只想对其进行有限的更改。您提出的解决方案涉及访问在多个翻译单元中定义的数据结构,就好像它们是单个数组的元素一样。

Q1。 C standard nor the C++ standard 都不包含链接器部分的概念,因此,不,没有真正独立于平台的方式来指定输出部分名称。

您需要检查您要定位的每个编译器。您已经找到了 GCC 和 Clang 的咒语。 Visual C++ 有 #pragma section and __declspec(allocate) ,它们一起可以实现同样的事情。

Q2。 GCC 使用平台的链接器构建可执行文件。假设是 GNU 环境,那么该链接器将是 binutils ld or gold. With these linkers, each output section is contiguous, and alignment of the input sections within the output section can be specified 或允许默认。根据文档,假设您的所有目标文件都是使用相同版本的 GCC 编译的,使用相同的编译器选项,默认值将适用于您。不同的编译器选项可能会导致不同的默认对齐方式。

Q3。关于平台上行为的差异:您对链接器的使用相当不寻常。您应该仔细测试您定位的每个平台。我建议构建一个小型二进制文件,以您想要的方式将目标文件放在一起,并(以编程方式)检查数据结构是否可以您想要的方式访问。

Q4。看起来您的方法适用于 Linux 上的 GCC/Clang/binutils 和 Windows 上的 Visual C++/LINK。了解每个平台的特性需要付出相当大的努力,但我认为您可以使用真正的键盘使您的方法在几乎任何 post-1995 平台上工作。您可能在较旧的机器和较小的嵌入式系统上遇到困难。您可能会继续 Android。我不确定 iOS。

作为一般建议,假设数据结构跨翻译单元边界是连续的来访问数据结构是不寻常的。您很可能 运行 遇到奇怪的问题并且很难获得帮助。这里有一些替代机制,可以让你得到你想要的东西,每个平台的工作量更少:

  1. 编译前将源文件放在一起,作为一个整体编译。如果无法手动完成,请考虑使用预处理器或构建一个小的 Perl 或 Python 脚本在构建时为您完成。

  2. 在运行时,动态分配一段连续的内存并将数据结构复制到其中。如果数据结构很小,这不会使用太多额外的内存。如果数据结构很大,包含原始结构的内存将被调出,这不会使用太多额外内存。

  3. 使用间接:让您的程序通过指向数据的指针数组访问数据结构。