首页 > 解决方案 > 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")));

标签: cgccmicrocontroller

解决方案


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对此有最好的解释。


推荐阅读