GCC错误"<variable>导致节类型冲突"

Evi*_*Pie 7 c gcc xc16

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

问题

C源:

int __attribute__((section(".in_my_data"))) _foo = 1;
int __attribute__((section(".in_my_data"))) _bar = 0;
Run Code Online (Sandbox Code Playgroud)

(相关)GCC编译器输出:

mcve/main.c:75:45: error: _bar causes a section type conflict
Run Code Online (Sandbox Code Playgroud)

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

.my_data : { *(.in_my_data) } > data
Run Code Online (Sandbox Code Playgroud)

更多的信息

更改C源以允许编译器使用两个部分允许编译通过,但是如果两个输入节被映射到相同的输出节,则链接器会生成错误.

C源:

int __attribute__((section(".in_my_data_nonzero"))) _foo = 1;
int __attribute__((section(".in_my_data_zero"))) _bar = 0;
Run Code Online (Sandbox Code Playgroud)

链接描述文件:

.my_data : { *(.in_my_data*) } > data
Run Code Online (Sandbox Code Playgroud)

(相关)链接器输出:

Link Error: attributes for input section '.in_my_data_nonzero' conflict
with output section '.my_data'
Run Code Online (Sandbox Code Playgroud)

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

题

对于初始化为零的变量,GCC编译器需要哪些属性,而不是那些用非零初始化的变量,反之亦然?

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

相关问题

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

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

...或者对于原因仍然是一个谜,可能是相关的:

据我所知,上述所有内容似乎都没有我可以在这个问题上申请的答案.

Evi*_*Pie 7

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

研究

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

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

这些中的第一个和最后一个是有意义的:.data用于初始化数据并.bss用于未初始化的数据.但是,.bssANSI C启动时数据也设置为零(参见注释2).

回答

这样看来,编译器包括变量被初始化,但是这相当于在所有位0的值.bss部分,以及所有的那些不是在所有初始化.

根据维基百科:

实现还可以向BSS部分分配静态分配的变量和用仅由零值比特组成的值初始化的常量.

解决方法

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

妄想

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

笔记

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

注2:标记变量__attribute__((noload))将导致变量从该.bss部分中排除.XC16生成一个特定的输出节,每个变量标记为(GUID?)唯一的名称.


小智 5

默认情况下,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
Run Code Online (Sandbox Code Playgroud)