2011-05-24 63 views
17

我有以前編譯C++程序,但用的Jamfiles碴後,該程序不再編譯和ld發出的duplicate symbol error的起源。這之後依次恢復到原來的Jamfiles,運行bjam clean,用手除去的對象,並從與所述的gcc前端鐺到在MacOS 10.6.7的gcc 4.2.1切換持續。瞭解一個鏈接複製符號錯誤

方案的簡化說明的是,有main.cpp和四個文件,a.h,cppb.h,cpp,其被編譯到鏈接到main.o靜態庫。 main.cppb.cpp都取決於包含違規符號off.h的文件,通過兩個不同的中間文件,但a.ha.cpp都不以off.h以任何方式依賴。

你問之前,我確信,所有文件都被包裹在多個定義衛士(#ifndef#define#endif),雖然我沒有發現失蹤了他們一個文件,它沒有引用off.h。更重要的是,b.h不包括任何引用off.h,只有實施,b.cpp,使得以off.h任何引用。這讓我感到困惑。

爲了增加我的困惑,我能夠從b.cpp中刪除對off.h的引用,並且如預期的那樣,它已成功重新編譯。但是,當我添加引用時,它也成功編譯,並在清除目標文件後繼續這樣做。對於爲什麼它未能編譯,我仍然感到茫然,特別是考慮到這些符號不應該衝突,我避免了符號重複,並且我已經擺脫了任何先前的/不完整的構建。

因爲我是能夠成功地編譯我的程序,我懷疑我能重現它來測試任何建議。但是,我很好奇這是如何發生的,如果我將來遇到這種情況,如果超出我所做的任何事情,我可以怎樣解決它?

+7

您期待我們診斷無法重現自己的錯誤? – 2011-05-24 20:07:53

+0

@尼爾,並非如此。注意:我能夠重現這個問題,以便在編譯時進行多次嘗試,直到遇到「解決方案」。而且,由於問題沒有再次出現,我預計答案會更加理論化,而不是具體化。但是,我試圖更好地理解什麼可能會導致在兩個單獨的編譯單元中引用的符號在不存在衝突時發生衝突。還有什麼,如果有的話,我可以採取額外的步驟來診斷和緩解這個問題。 – rcollyer 2011-05-24 20:18:37

+1

我想給你90%的機會,實際上並沒有清除所有的目標文件(可能是libtool或其他東西將它們隱藏在隱藏的目錄中?)。儘管如此,如果你不能複製它,那麼就沒有辦法做到這一點。 – bdonlan 2011-05-24 20:41:38

回答

39

這通常是在頭文件中定義的對象,而不是僅僅宣告它的結果。試想一下:

h.h

#ifndef H_H_ 
#define H_H_ 
int i; 
#endif 

a.cpp

#include "h.h" 

b.cpp

#include "h.h" 
int main() {} 

這將產生一個副本符號i。解決方案是在頭文件中聲明對象:extern int i;,並在其中一個源代碼文件中定義它:int i;

+2

這個符號是一個在頭文件中內聯聲明的函數,但缺少關鍵字'inline' [this](http://stackoverflow.com/questions/2954256/duplicate-symbol-linker-error-c-help)建議的是必要的。但是,我對你的解決方案的問題是,爲什麼在對象文件'a.o'中的int i'暴露在與'b.o'中的''相沖突的地方?據我瞭解,這不應該發生。我錯過了什麼? – rcollyer 2011-05-24 21:22:13

+2

1)在文件範圍聲明的名稱具有外部鏈接。 2)一個對象可以在多個翻譯單元中聲明,但必須精確定義一次。 – 2011-05-24 21:39:31

+0

我對此的看法越多,這似乎就越可能是原因。但是,除非我能重複,否則我仍然會爲它爲什麼編寫一天而不是下一個編輯而感到困惑。 – rcollyer 2011-06-01 03:29:45