c - Arm Gcc 弱别名重定义
问题描述
我想为几个函数创建弱别名,以便我可以在头文件中声明它,然后稍后在不同的文件中定义它。出于某种原因,我仍然从 gcc 收到重新定义错误。
理想情况下,对于没有实现的函数,我希望它默认返回别名。
我已经尝试删除 alias("Default_Handler") 并且它似乎可以编译,但它有点破坏了我对我正在尝试编写的这个应用程序的意图。
向量表.h
void __attribute__((noreturn)) Default_Handler (void);
void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
启动.c
#include "vector_table.h"
void Default_Handler(void){
for(;;);
}
void NMI_Handler(void){
for(;;);
}
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -Wall -Wno-unused -Wextra -pedantic -H -g3 -gdwarf-2 -O0 -std=c90 -ffreestanding -c startup.c
startup.c:93:6: error: redefinition of 'NMI_Handler'
void NMI_Handler(void){
^
In file included from startup.c:3:0:
vector_table.h:17:6: note: previous definition of 'NMI_Handler' was here
void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
解决方案
TL;DR:不要放入或__weak__
归档。放入并归档。__alias__
.h
__weak__
__alias__
.c
弱符号理论上是这样工作的:
- 有一个
.o
带有__weak__
符号的文件。 - 还有另一个
.o
带有正常符号的文件。 - 链接器看到两个符号并选择非弱符号。
.o
目标文件是从文件中生成的.c
。内部符号的定义.c
应该是弱的。
应用于声明的属性应用于看到它的定义。在声明__weak__
的标头中进行操作将所有看到该符号声明的定义标记为__weak__
.
alias
就像你会做的那样:
static inline void NMI_Handler(void) {
Default_Handler();
}
它的工作方式好像相同,但没有分支(并且打字更少)。无论如何,因为alias
创建了符号,所以它作为一个定义 - 它也属于一个.c
文件。这就是您收到多个定义错误的原因 -__alias__
定义了符号NMI_Handler
,然后您再次定义void NMI_Handler(void) {}
。
你想要做的我认为是这样的:
// vector_table.h
void __attribute__((noreturn)) Default_Handler (void);
void NMI_Handler(void);
// startup.c
void Default_Handler(void){
for(;;);
}
__attribute__((__weak__, __alias__("NMI_Handler")))
void NMI_Handler(void);
这与gcc 关于函数属性的文档中解释的示例用法相同。文档指出,别名的另一个符号必须在同一个事务单元中定义(读作:在同一个.c
文件中)。
请记住,将符号声明为弱符号并不意味着链接器将使强符号达到峰值 - 当使用静态库编译时,有时会发生奇怪的事情。仅使用对象编译或使用-Wl,-start-group
链接器选项。我认为infocenter.arm对此有最好的解释。
推荐阅读
- c++ - CURLOPT_INTERLEAVEFUNCTION 回调函数总是接收 nullptr 作为用户数据指针
- clickhouse - dictGetString 在 clickhouse 中创建的 DDL 字典上失败
- node.js - 如何使用 mongoose 和 nodejs 从 mongodb 获取与每条记录匹配的所有数据
- node.js - 为什么 Puppeteer 在页面上找不到这个链接元素?
- c++ - 获取 LoadLibrary 无法加载 DLL 的原因
- python - 根据值的时间增量更新字典
- css - CSS:对齐标题和内容线性渐变背景
- r - 在 Markdown 中为 Word 文档导出的图环绕文本
- homebrew - 如何将 Homebrew 降级到旧版本?
- python - 使用 Python 建立 SSH 隧道