提问人:Dale Wheat 提问时间:11/3/2023 更新时间:11/3/2023 访问量:66
尝试覆盖 C 中的弱函数时出现“错误:重新定义”
Getting “error: redefinition” when trying to override weak functions in C
问:
我正在尝试编写一些C库代码,为RV32EC微控制器(CH32V003)创建系统和设备中断向量表。它与 ARM Cortex-M 向量表的布局方式几乎相同:除非另有说明,否则弱定义的函数指针数组指向默认处理程序。然后,当我或库的某个未来用户想要定义他们自己的中断处理程序时,只需创建它,它就会覆盖默认条目。当我尝试覆盖默认函数时,我收到“错误:重新定义”。
我在 MacOS Sonoma 上使用 xpack-riscv-none-elf-gcc-13.2.0-2 GCC 工具链。我已经为这些芯片编写了几十个其他小程序,这些程序要么使用无中断,要么使用CH32V003上可用的其他一些中断处理方案,例如无向量表和均匀中断,并取得了成功。
在我的main.c文件的顶部附近,我有这样的代码:
// system vectors
// these are function prototypes that are supposed to be in the main.h header file
__attribute__ ((weak, interrupt)) void system_vector_default(void); // reserved slot(s) in system vector table
__attribute__ ((weak, interrupt, alias("system_vector_default"))) void system_vector_NMI(void); // non-maskable interrupt handler
__attribute__ ((weak, interrupt, alias("system_vector_default"))) void system_vector_HardFault(void); // hard fault handler
__attribute__ ((weak, interrupt, alias("system_vector_default"))) void system_vector_SysTick(void); // SysTick interrupt handler
__attribute__ ((weak, interrupt, alias("system_vector_default"))) void system_vector_SW(void); // software interrupt
void system_vector_default(void) { // reserved slot(s) in system vector table
// note: this definition is required, as all the other weakly-linked functions point to it
}
void system_vector_NMI(void) {} // non-maskable interrupt handler
//void system_vector_HardFault(void) {} // hard fault handler
//void system_vector_SysTick(void) {} // SysTick interrupt handler
//void system_vector_SW(void) {} // software interrupt
__attribute__ ((section(".system_vector"))) void (* const system_vector_table[]) (void) = { // system vector table, skipping vector 0 (reserved)
system_vector_default, // 1 - reserved
system_vector_NMI, // 2 - non-maskable interrupt handler
system_vector_HardFault, // 3 - hard fault interrupt handler
system_vector_default, // 4 - reserved
system_vector_default, // 5 - reserved
system_vector_default, // 6 - reserved
system_vector_default, // 7 - reserved
system_vector_default, // 8 - reserved
system_vector_default, // 9 - reserved
system_vector_default, // 10 - reserved
system_vector_default, // 11 - reserved
system_vector_SysTick, // 12 - SysTick interrupt handler
system_vector_default, // 13 - reserved
system_vector_SW, // 14 - software interrupt handler
system_vector_default, // 15 - reserved
};
当我定义“system_vector_default()”函数而没有定义其他函数时,代码可以完美地编译并生成一个仅包含指向“system_default_vector()”函数的指针的向量表。这正是我想要的。
当我取消注释“system_vector_NMI()”函数的定义(如上所述)或任何其他“system_vector_*()”函数时,我收到以下错误消息:
main.c:22:6: error: redefinition of 'system_vector_NMI'
22 | void system_vector_NMI(void) {} // non-maskable interrupt handler
| ^~~~~~~~~~~~~~~~~
main.c:12:72: note: previous definition of 'system_vector_NMI' with type 'void(void)'
12 | __attribute__ ((weak, interrupt, alias("system_vector_default"))) void system_vector_NMI(void); // non-maskable interrupt handler
| ^~~~~~~~~~~~~~~~~
make: *** [J4-weak.elf] Error 1
编译器准确地告诉我它认为令人反感的东西:“system_vector_NMI()”函数的“原型”。也许我不明白函数原型是什么,也不知道如何使用:我以为它是一个“函数签名”,即返回类型和参数类型,没有函数体定义。
在互联网上搜索这个错误给我带来的只有羞耻。这是一个常见的初学者问题,尤其是当你不小心递归地包含一些带有声明的头文件时。我努力将“#include 守卫”添加到我的所有头文件中。在此示例中,为了清楚起见,我将所有代码直接导入到单个源文件中。我什至尝试将所有与矢量相关的东西放入其自己的vector.c/vector.h文件中,并发生相同的编译器错误。
因此,我希望编译器做的是创建我的系统向量表,使用未定义函数的默认值,但替换库用户提供的任何函数的地址。
所以我正在做“错误的事情”,我敢肯定,在这一点上,它要么是基于我对这些事情应该如何运作的无知,要么是我在此过程中做出的一些不正确的假设。
答: 暂无答案
评论
alias
system_vector_default
system_vector_default
system_vector_NMI
alias
void system_vector_NMI(void) {}