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

时间:2013-03-20 13:53:41

标签: c++ c linker

使用特殊编译器命令可以将符号声明为 weak According to Wikipedia

  

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

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

5 个答案:

答案 0 :(得分:17)

弱链接的一个用途是在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;

这些是必须由实现提供的函数,但如果程序实现它们,则程序的实现将替换或覆盖实现的版本。这可以通过弱连接轻松实现。

答案 1 :(得分:16)

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

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

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

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

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

答案 2 :(得分:6)

  

The weak属性导致声明以弱的形式发出   符号而不是全球。这主要用于定义   可以在用户代码中覆盖的库函数   也可以与非函数声明一起使用。弱符号是   支持ELF目标,也支持a.out目标使用时   GNU汇编器和链接器。

The weak attribute example

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表示未定义的弱符号。

答案 3 :(得分:6)

典型的和日常用例是内联和模板功能。

例如,使用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”符号的冲突,或者编译器将无法禁用内联

答案 4 :(得分:3)

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