【问题标题】:How to force the linker to resolve weak symbols locally?如何强制链接器在本地解析弱符号?
【发布时间】:2015-02-01 20:47:10
【问题描述】:

使用 g++,当两个编译单元“a1.o”和“a2.o”都定义和使用相同的弱符号时,链接器将静默解析到符号的第一次出现。因此,应用程序的行为将取决于链接器命令行上目标文件的顺序。可以做些什么来确保这些符号在本地解析到每个编译单元?

例如,作为一个极简主义的例子,如果我有以下源文件:

a1.cpp:

#include <iostream>
struct A
{
    void foo() {std::cerr << __FILE__ << std::endl;}
};
void bar1() {A a; a.foo();}

a2.cpp:

#include <iostream>
struct A
{
    void foo() {std::cerr << __FILE__ << std::endl;}
};
void bar2() {A a; a.foo();}

main.cpp:

void bar1();
void bar2();
int main()
{
    bar1();
    bar2();
}

并编译它们:

for i in a1 a2 main ; do g++ -c -o $i.o $i.cpp ; done

输出将取决于链接器命令行上 a1.o 和 a2.o 的相对位置:

g++ -o main main.o a{1,2}.o ; ./main
a1.cpp
a1.cpp

g++ -o main main.o a{2,1}.o ; ./main
a2.cpp
a2.cpp

我希望获得与使用“-fno-weak”命令行选项相同的结果:

for i in a1 a2 main ; do g++ -fno-weak -c -o $i.o $i.cpp ; done
g++ -o main main.o a{1,2}.o ; ./main
a1.cpp
a2.cpp

但“-fno-weak”似乎会导致其他并发症。有哪些替代方案(除了不内联和修复冲突)?

对于那些想知道什么是典型用例的人:在编写模拟组件时,有时只使用标头实现会很方便。不同的测试夹具最终具有相同组件类型的不同模拟实现,当所有夹具都链接到单个测试运行器时,这将成为一个问题。

【问题讨论】:

  • 我不明白,如果你想要本地实现,你为什么将它们定义为弱符号?
  • @Kam 是编译器将它们定义为弱符号。另一种表述问题的方法:如何告诉编译器为成员函数生成局部符号?

标签: c++ linker g++ ld


【解决方案1】:

你问:

有哪些替代方案(除了不内联和修复冲突)?

使用本地namespaces 或匿名namespaces。

a1.cpp:

#include <iostream>
namespace A1_namespace
{
   struct A
   {
      void foo() {std::cerr << __FILE__ << std::endl;}
   };
}

using namespace A1_namespace;

void bar1() {A a; a.foo();}

#include <iostream>
namespace
{
   struct A
   {
      void foo() {std::cerr << __FILE__ << std::endl;}
   };
}

void bar1() {A a; a.foo();}

对 a2.cpp 进行类似的更改。

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 2017-06-14
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    相关资源
    最近更新 更多