2014-12-04 44 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類似的變化。