2014-12-04 46 views
2

使用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弱”的命令行选项:

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弱”似乎引发其他并发症。有哪些选择(除了不内联和固定碰撞)?

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

+0

我不明白,如果你想本地实现,为什么你将它们定义为弱符号? – Kam 2014-12-04 04:28:32

+0

@Kam编译器将它们定义为弱符号。制定问题的另一种方法是:如何告诉编译器为成员函数生成本地符号? – 2014-12-04 16:44:34

回答

4

你问:

有什么选择(除了没有内联和固定碰撞)?

使用本地namespace或匿名namespace s。

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类似的变化。

相关问题