【问题标题】:How can I guarantee the position of data inside a separate linker section does not change when I extend it?当我扩展一个单独的链接器部分时,如何保证数据的位置不会改变?
【发布时间】:2025-12-14 22:20:07
【问题描述】:

在嵌入式 C++ 上下文中,我在闪存中定义了一个单独的链接器部分,远离其余代码/数据,我在其中存储用户可以在运行时修改的数据。 (基本上是 EEPROM 仿真)

我还有一个自定义设备固件更新程序,它将覆盖闪存中的只读代码/数据,除了本节(以及固件更新程序的部分),因为我希望用户对持久配置进行更改即使他们执行固件更新,也会持续存在。

作为这些固件的一部分,我可能会扩展用户可以执行的配置数量。所以,我有一个代码文件,它本质上是一个全局变量列表,它在闪存中的给定位置链接,并在最后添加行。当然,我真的很想确保之前在这里的变量在内存中的位置不会改变。

我对此有什么保证?通过Memory layout of globals,我不确定我是否能保证在文件末尾按顺序添加行不会改变先前变量的位置。

我相信结构中相同访问级别的数据成员将始终由编译器在内存中排序,因此我可以在某个地方定义一个结构,在我的专用链接器部分中对其进行实例化,并使用未来的更新对其进行扩展。但即便如此,我对对齐保证的了解也足够多,以至于我对它们知之甚少,所以我仍然不确定自己是否安全。

那么,我该怎么做呢?

【问题讨论】:

  • 使用链接器指令文件,在固定地址或偏移处声明段。使用编译器特定的操作(pragma?)将变量分配给段(在源代码中)。因此,例如,我们可以定义一个名为 FLASH 的段,然后在源代码中告诉编译器我们希望将一个变量(或常量)放入 FLASH 段中。在链接器指令文件中,我们将创建 FLASH 段并声明其地址或位置。
  • @ThomasMatthews 这就是我正在做的事情,但是有一个变量文件。如果可能的话,我不想对我的每一个持久变量的地址进行微观管理。

标签: c++ memory linker embedded


【解决方案1】:

几个编译器和/或链接器通过一些(对我们用户而言)未知(散列?)算法对变量进行排序。如果重命名变量或添加变量,每个变量都可能更改其位置。

但是,正如标准在第 6.5.2.3 章第 6 段(我强调)中所说,有帮助:

为了简化联合的使用,我们做了一个特殊的保证:如果联合包含多个共享相同初始序列的结构(见下文),并且如果联合对象当前包含这些结构之一,则允许在可以看到联合的完整类型声明的任何地方检查它们中任何一个的公共初始部分。 如果对应的成员对于一个或多个初始成员的序列具有兼容的类型(并且对于位域,具有相同的宽度),则两个结构共享一个共同的初始序列。

因此,如果您为保存的数据定义一个结构,您可以毫无顾忌地添加新成员。使用此结构来定义保存值的单个变量。

此外,您还可以定义结构的联合,它们具有共同的初始成员序列,您可以使用它来区分后续成员的序列。

无论如何,您需要通过适当的属性和链接描述文件条目来定位这个单一变量。但你已经这样做了。

【讨论】:

    最近更新 更多