7

为什么在尝试将两个仅在初始化值不同的(RAM)变量放入同一部分时会出现编译器错误?

问题

C源:

int __attribute__((section(".in_my_data"))) _foo = 1;
int __attribute__((section(".in_my_data"))) _bar = 0;

(相关的)GCC编译器输出:

mcve/main.c:75:45: error: _bar causes a section type conflict

链接器脚本在定义中包含以下行SECTIONS,但(致命)错误来自编译器,而不是链接器。

.my_data : { *(.in_my_data) } > data

更多信息

更改 C 源代码以允许编译器使用两个节允许编译通过,但如果两个输入节映射到同一个输出节,则链接器会生成错误。

C源:

int __attribute__((section(".in_my_data_nonzero"))) _foo = 1;
int __attribute__((section(".in_my_data_zero"))) _bar = 0;

链接器脚本:

.my_data : { *(.in_my_data*) } > data

(相关)链接器输出:

Link Error: attributes for input section '.in_my_data_nonzero' conflict
with output section '.my_data'

在 C 源代码中交换行的顺序只会改变哪个部分(出现在 C 源代码中的第二个)是错误的。

问题

对于以零初始化的变量,对于以非零初始化的变量,GCC 编译器需要哪些属性,反之亦然?

编译器是否试图将初始化为零的变量放在该.bss部分中,而不是.data用于初始化数据的部分?或者是否有另一部分用于初始化为零的数据?

相关问题

出现的类似问题涵盖了内存类型(ROM 与 RAM)之间的冲突问题:

...或将初始化const数据放入 NOLOAD 输出部分:

... 或者对于原因仍然是一个谜,并且可能与此有关:

据我所知,以上任何一个似乎都没有我可以在这个问题上申请的答案。

4

2 回答 2

8

默认情况下,GCC 将对象类放在不同的部分,可执行代码放在 .text 中,初始化数据放在 .data 中,静态数据放在 .bss 中,还有一些更晦涩的部分。

如果你试图强制两个不同类的对象属于同一个节,GCC 会引发这个节错误。

解决方案是将它们放在不同的部分中,最后告诉链接器最终将这些对象合并到同一部分中,例如:

.boot : {                 // target ELF section will contain....
    *(.boot)              // executable code
    *(.boot_rodata)       // constant data
    *(.boot_bss)          // static data
} > BOOT                  // to finally be place in this area
于 2015-10-16T11:41:02.687 回答
7

警告:此答案可能仅适用于 Microchip XC16 编译器。

研究

编译器将属性分配给 C 变量,以便将它们分配给特定部分,如下所示(有关 XC16 特定信息,请参见下面的注释 1 )。

  • int a = 1;- 分配给.data
  • int b = 0;- 分配给.bss
  • int c;- 分配给.bss

其中第一个和最后一个有意义:.data用于初始化数据并.bss用于未初始化数据。然而,.bss数据也被 ANSI C 启动设置为零(见注 2)。

回答

似乎编译器包含初始化的变量,但其值等于该.bss部分中的所有位 0 以及所有未初始化的位。

根据维基百科

实现还可以将静态分配的变量和常量分配给 BSS 部分,该变量和常量初始化为一个仅由零值位组成的值。

解决方法

GCC 有一个选项-fno-zero-initialized-in-bss,可用于强制以零初始化的所有变量进入该.data部分,如本答案中所述。这可以应用于每个源文件,但不能应用于单个变量。

妄想

如果有一个__attribute__((**doload**))可以用来强制编译器放置一个零初始化变量.data而不是.bss.

笔记

注 1:XC16 编译器可以使用.ndata.nbss来指示地址 0x8000 以下的附近数据。

注意 2:将变量标记为__attribute__((noload))将导致该变量被排除在该.bss部分之外。XC16 生成一个特定的输出部分,每个变量都有一个(GUID?)唯一名称标记为这样。

于 2015-05-06T16:00:49.247 回答