GCC 错误“<variable> 导致节类型冲突”
GCC error "<variable> causes a section type conflict"
为什么在尝试将两个 (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)之间的冲突问题:
- "Section type conflict" in arm embedded, what is it?
- How do I resolve a "section type conflict" compile error and best practices for using section attribute with gcc
- Getting a "section type conflict" using M2tklib and glcd
... 或将初始化的 const
数据放入 NOLOAD 输出部分:
- "Section type conflict" due to macro definition in GCC 4.8.2
... 或成因仍是个谜,可能与以下有关:
- Section type conflict for identically defined variables
据我所知,上面的 None 似乎有一个我可以应用于此问题的答案。
警告:此答案可能仅适用于 Microchip XC16 编译器。
研究
编译器将属性分配给 C 变量,以便将它们分配给特定的部分,如下所示(有关 XC16 的特定信息,请参见下面的 注 1)。
int a = 1;
- 分配给 .data
.
int b = 0;
- 分配给 .bss
.
int c;
- 分配给 .bss
.
第一个和最后一个有意义:.data
用于初始化数据,.bss
用于未初始化数据。然而,.bss
数据也被 ANSI C 启动设置为零(参见 注 2)。
回答
编译器似乎包含 被 初始化的变量,但其值等于 .bss
部分中的所有位 0 以及所有那些根本没有初始化的。
根据wikipedia:
An implementation may also assign statically-allocated variables and constants initialized with a value consisting solely of zero-valued bits to the BSS section.
解决方法
GCC 有一个选项 -fno-zero-initialized-in-bss
,可用于强制所有初始化为零的变量进入 .data
部分,如 this answer 中所述。这可以应用于每个源文件,但不能应用于单个变量。
如意算盘
如果有一个 __attribute__((**doload**))
可以用来强制编译器在 .data
而不是 .bss
中放置一个零初始化变量,那就太好了。
备注
注1:XC16编译器可能使用.ndata
和.nbss
来表示地址0x8000以下的near数据。
注意 2:用 __attribute__((noload))
标记变量将导致变量被排除在 .bss
部分之外。 XC16 生成一个特定的输出部分,每个变量都有一个(GUID?)唯一名称。
默认情况下,GCC 将 classes 对象放在不同的部分,可执行代码到 .text,初始化数据到 .data,静态数据到 .bss,还有一些更模糊的。
如果您试图强制两个不同 class 的对象属于同一部分,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
为什么在尝试将两个 (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)之间的冲突问题:
- "Section type conflict" in arm embedded, what is it?
- How do I resolve a "section type conflict" compile error and best practices for using section attribute with gcc
- Getting a "section type conflict" using M2tklib and glcd
... 或将初始化的 const
数据放入 NOLOAD 输出部分:
- "Section type conflict" due to macro definition in GCC 4.8.2
... 或成因仍是个谜,可能与以下有关:
- Section type conflict for identically defined variables
None 似乎有一个我可以应用于此问题的答案。
警告:此答案可能仅适用于 Microchip XC16 编译器。
研究
编译器将属性分配给 C 变量,以便将它们分配给特定的部分,如下所示(有关 XC16 的特定信息,请参见下面的 注 1)。
int a = 1;
- 分配给.data
.int b = 0;
- 分配给.bss
.int c;
- 分配给.bss
.
第一个和最后一个有意义:.data
用于初始化数据,.bss
用于未初始化数据。然而,.bss
数据也被 ANSI C 启动设置为零(参见 注 2)。
回答
编译器似乎包含 被 初始化的变量,但其值等于 .bss
部分中的所有位 0 以及所有那些根本没有初始化的。
根据wikipedia:
An implementation may also assign statically-allocated variables and constants initialized with a value consisting solely of zero-valued bits to the BSS section.
解决方法
GCC 有一个选项 -fno-zero-initialized-in-bss
,可用于强制所有初始化为零的变量进入 .data
部分,如 this answer 中所述。这可以应用于每个源文件,但不能应用于单个变量。
如意算盘
如果有一个 __attribute__((**doload**))
可以用来强制编译器在 .data
而不是 .bss
中放置一个零初始化变量,那就太好了。
备注
注1:XC16编译器可能使用.ndata
和.nbss
来表示地址0x8000以下的near数据。
注意 2:用 __attribute__((noload))
标记变量将导致变量被排除在 .bss
部分之外。 XC16 生成一个特定的输出部分,每个变量都有一个(GUID?)唯一名称。
默认情况下,GCC 将 classes 对象放在不同的部分,可执行代码到 .text,初始化数据到 .data,静态数据到 .bss,还有一些更模糊的。
如果您试图强制两个不同 class 的对象属于同一部分,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