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

问题描述:

使用特殊的编译器命令可以声明一个符号According to Wikipedia弱链接的实际应用是什么?

弱符号在目标文件或动态库中的符号定义,可以由其他符号覆盖定义

在什么情况下或为了什么应用程序,你需要弱符号?典型的用例是什么?

+1

https://ofekshilon.com/2014/02/10/linker-weak-symbols/ – 2016-09-21 09:01:12

一个使用弱联在正在实施更换功能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; 

这些都是必须由实现提供的功能,但如果一个程序实现他们则计划实施替代或覆盖实现的版本。这很容易通过弱连接来实现。

+0

@BernhardKausler提供了一些相关的SO问题,可能会给出更多的见解:[为什么要替换默认的新的和删除操作符?](http://*.com/questions/7149461/why-would-one -replace-default-new-and-delete-operators)[如何正确替换全局new和delete操作符](http://*.com/questions/8186018/how-to-properly-replace-global-new-delete [操作符] [我应该如何编写符合ISO C++标准的自定义新的和删除操作符?](http://*.com/questions/7194127/how-should-i-write-iso-c-standard-conformant-custom-新和删除运营商) – bames53 2013-03-21 15:03:51

在嵌入式开发,当你有例如中断指针的载体,这是非常方便的,能够使用弱链接获取默认处理程序打断你不感兴趣的内容。

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

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

这通常是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. */ 

然后在需要时,你可以实现自己的功能:

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

而不必改变任何东西,它“只是工作”。当然,只要您的名字是上述“支持代码”所期望的名称即可。

The weak属性促使发射作为一个弱 符号,而不是一个全球性的声明。这在定义 库函数时非常有用,它可以在用户代码中覆盖,但 也可以用于非函数声明。对于ELF目标,弱符号支持 ,对于使用GNU汇编器和链接器的 也支持a.out目标。

The weak attribute example

weak.c

extern void foo() __attribute__((weak)); 

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

的foo.c

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

强。ç

extern void foo() ; 

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

编译

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

当 “foo” 被宣布为弱,它的定义可以省略, 或更换不同的库,具有样“链接时间 绑定”。链接器将为未定义的弱符号填入0。

当您希望能够在代码的另一部分覆盖函数定义时,通常使用弱链接。这在典型的例如图书馆中就是这种情况。一个默认的错误处理程序,如果您使用该库,您可以使用自定义函数覆盖该错

典型的和每一天的用例都是内联和模板函数。

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

extern void a(); 

inline void foo() { a(); } 

void bar() { foo(); } 
void baz() { foo(); } 

本来符号bar和baz通过nm标记为T(正常)和Foo将被标记为W - 弱。

(即mn -C ./a.out

理由:

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

如果将未标记为弱,将是多个“foo”的符号碰撞或编译器将无法禁用内联

+0

因此,大多数模板函数也很弱。 – 2013-03-20 15:15:08

+0

@MatthieuM。的确,添加到答案 – Artyom 2013-03-20 19:32:25