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

时间:2016-10-21 06:38:38

标签: c++ gcc llvm

我想把一些带有静态链接的对象放在一起,而没有任何其他数据交错。对象在单独的源文件中定义。订单无关紧要,只要它们是连续的(除了最小/标准填充)。

在gcc中,我可以使用__attribute__((section("mydata")))实现此目的,但AFAIK具有GCC特定且只有许多编译器支持它(gcc,llvm和其他几个,但我认为不是msvc) ,对于许多目标(精灵是的,其他我不确定,我怀疑)。

Q1:有没有一种标准的方法来实现这一目标?

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

问题3:GCC与支持此属性的其他编译器之间的行为是否存在差异?

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

1 个答案:

答案 0 :(得分:1)

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

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

您需要检查要定位的每个编译器。你已经找到了GCC和Clang的咒语。 Visual C ++有#pragma section__declspec(allocate),它们可以实现相同的功能。

Q2。 GCC使用平台的链接器来构建可执行文件。假设一个GNU环境,那么该链接器将是binutils ldgold。使用这些链接器,每个输出部分是连续的,并且输出部分内的输入部分的对齐可以是specified或允许默认。根据文档,默认将适用于您假设您使用相同的编译器选项使用相同版本的GCC编译所有目标文件。不同的编译器选项可能导致不同的默认对齐。

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

Q4。看起来你的方法适用于Linux上的GCC / Clang / binutils和Windows上的Visual C ++ / LINK。学习每个平台的idosyncracies需要花费一些力气,但我认为你可以让你的方法适用于任何带有真正键盘的1995年后平台。您可能在旧机器和较小的嵌入式系统上遇到困难。你可以在Android上使用它。我不确定iOS。

作为一般建议,通过假设它们在翻译单元边界上是连续的来访问数据结构是不寻常的。您可能会遇到奇怪的问题并且很难获得帮助。以下是一些备用的机制可能会让您获得所需的内容,而每个平台的工作量更少:

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

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

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