弱连接的实际应用是什么?

使用特殊编译器命令可以将符号声明为 。 根据维基百科 :

弱符号是对象文件或动态库中的符号定义,可以被其他符号定义覆盖

在什么场景或什么应用程序你需要弱符号? 什么是典型用例?

弱链接的一个用途是实现C ++标准中的可替换函数。 即:

void *operator new(std::size_t); void *operator new(std::size_t, std::nothrow_t const &) noexcept; void *operator new[](std::size_t); void *operator new[](std::size_t, const std::nothrow_t&) noexcept; void operator delete(void *) noexcept; void operator delete(void *, std::nothrow_t const &) noexcept; void operator delete[](void *) noexcept; void operator delete[](void *, std::nothrow_t const &) noexcept; 

这些是必须由实现提供的函数,但是如果程序实现它们,那么程序的实现将替换或覆盖实现的版本。 这很容易通过弱连接实现。

在嵌入式开发中,当您拥有一个中断指针向量时,能够使用弱链接获取您不感兴趣的中断的默认处理程序非常方便。

这通过定义一个空处理程序(一次),然后为您需要的每个中断指针引入一个新的正确命名符号来工作,该指针与默认处理程序弱链接。

然后向量填充这些符号,这些符号都指向相同的实际代码,直到您决定使用相同(正确)的名称实现其中一个,然后您的代码“覆盖”弱链接,从而导致指向您的指针要在中断表中安装的代码。

这通常是在C和汇编的某种混合中实现的,但是使用C伪代码我们可能会有类似的东西:

 static void placeholder_isr(void) { } /* Introduce properly-named function pointers, with weak linking. * NOTE: This syntax is completely fictional as far as I know. */ void (*timer1_isr)() = placeholder_isr __attribute("weak linking"); void (*timer2_isr)() = placeholder_isr __attribute("weak linking"); void (*usart1_isr)() = placeholder_isr __attribute("weak linking"); void (*usart2_isr)() = placeholder_isr __attribute("weak linking"); void (*dma1_isr)() = placeholder_isr __attribute("weak linking"); void (*dma1_isr)() = placeholder_isr __attribute("weak linking"); /* Declare the table of interrupt handlers. */ static void (*isr_table)[] = { timer1_isr, timer2_isr, usart1_isr, usart2_isr, dma1_isr, dma2_isr, } __attribute("isr vector"); /* Attribute to place it where it needs to go. */ 

然后你可以在需要时实现自己的function:

 void timer1_isr(void) { /* Handler ISR from timer1. */ } 

它不需要改变任何其他东西,它“只是有效”。 当然,只要您的名字是上述“支持代码”所期望的名称。

weak属性导致声明作为弱符号而不是全局符号发出。 这主要用于定义可以在用户代码中重写的库函数,尽管它也可以与非函数声明一起使用。 ELF目标支持弱符号,并且在使用GNU汇编器和链接器时也支持a.out目标。

弱属性示例 :

weak.c

 extern void foo() __attribute__((weak)); int main() { if (foo) foo(); } 

foo.c的

 void foo() { printf("in foo.\n"); } 

strong.c

 extern void foo() ; int main() { if (foo) foo(); } 

编译

 $ cc weak.c // Compiles OK $ cc strong.c // undefined reference to `foo' 

当声明“foo”弱时,它的定义可以省略,或者被不同的库替换,具有“链接时绑定”的类型。 链接器将为未定义的弱符号填充0。

典型的和每天的用例是内联和模板function。

例如,使用g++ -shared -fPIC编译时的这部分代码:

 extern void a(); inline void foo() { a(); } void bar() { foo(); } void baz() { foo(); } 

将符号bar和baz标记为T(正常)为nm ,foo将标记为W – 弱。

(即mn -C ./a.out

理由:

内联函数和模板可以在头文件中定义,并且通常在源的不同部分中多次定义,最后只有一个保持活动状态。

如果它没有被标记为弱,那么它将是多个“foo”符号的冲突,或者编译器将无法禁用内联

当您希望能够覆盖代码的另一部分中的函数定义时,通常使用弱链接。 这通常是库中指定例如默认error handling程序的情况,如果使用库,则可以使用自定义函数覆盖该error handling程序。