回答
其中之一或兩者。它也可能源於程序員編輯源代碼或修改構建腳本。
當鏈接器找到兩個具有相同名稱的東西(符號)時,會發出「重新定義」錯誤。
鏈接器可能會找到兩個具有相同名稱的符號的原因很多。一些可能性(有許多排列)包括;
- 目標文件在鏈接命令中指定了兩次。這通常是由構建腳本中的錯誤造成的。
- 兩個包含相同函數定義的目標文件。這是代碼複製的結果 - 例如,函數定義被複制到不同的源文件中,然後進行編譯和鏈接。它也可能來自與預處理器的猴業務(例如
#include
ing文件包含由兩個源文件定義的全局變量)。
的東西,如上述的原因通常是程序員錯誤(例如,在構建腳本供給壞接頭命令,項目之間的預處理器,複製和粘貼代碼的誤用。
原因在庫中的函數像libc通常可以被「重載」,就是鏈接器通常只在庫中找到符號,如果它在對象文件中找不到它們的話,那麼,如果一個目標文件定義了malloc()
,鏈接器將解析所有的調用,而不是嘗試在庫中使用版本來解析這種事情是相當危險的,因爲庫中的一些其他函數(例如,甚至在libc中)可能直接解析爲原始的malloc()
(例如一些調用可能被內聯),這可能會導致不可預知的行爲。這種行爲也是特定於鏈接器的:雖然這種情況在unix/linux變體中很常見,但有些系統中連接器的做法各不相同。
如果您有兩個具有相同原型或簽名的函數(函數簽名由參數和參數類型的函數名稱數量構成,不包含返回類型),則會得到函數重定義錯誤。
這是一個編譯時錯誤,如果編譯器看到兩個函數具有相同簽名:
int foo(int a);
double foo(int b);
爲什麼你可以重寫庫函數調用?讓我們來看看代碼是如何建成的可執行文件:
- 編譯器被稱爲爲每個源文件和輸出的目標文件:任何函數調用不能被解析(即調用在不同文件中的函數)鏈接器必須解決的外部符號。
- 鏈接器獲取所有對象文件並嘗試解析所有符號;但它是以先到先得的方式完成的。對於外部符號,它會考慮它找到的第一個定義,而不用擔心可能存在更多相同符號的定義。
因此,鏈接器實際上允許您覆蓋函數的行爲。這一切都取決於文件鏈接的順序 - 它找到的第一個函數定義是用於解析符號的函數。
希望對此有所瞭解。
謝謝Pandrei, 做的「先到先得」方式只適用於共享庫嗎? 這裏是我想要的,main.cpp調用def1.cpp和def2.cpp中定義的函數: gcc main.cpp def1.cpp def2.cpp //多重定義錯誤 但是 gcc main.cpp def1。所以def2.so //是的,先到先得的方式 有什麼區別? –
@ SamH.W不,它不適用於圖書館;實際上鍊接器並不知道區別;它只接收一堆目標文件並嘗試解析這些符號。試試這個:一個帶有函數原型的頭文件,兩個源文件,每個帶有它自己的實現,並在main()中調用該函數。即使您對同一個函數有兩個不同的實現,也應該創建它。 – Pandrei
- 1. GTK3程序不再編譯 - 鏈接時GCC「未定義參考」
- 2. 編譯和鏈接bash配置腳本在哪裏發生?
- 3. 當更新靜態庫時,主應用程序必須重新編譯或重新鏈接?
- 4. Docker重新編譯時間
- 5. Opencv源編譯與cuda生成多個定義鏈接錯誤
- 6. 鏈接庫是編譯時間鏈接到另一個庫
- 7. 重新定位鏈接程序
- 8. 安裝是否在運行時或編譯期間發生?
- 9. 在運行時或編譯/鏈接時綁定模塊的接口要求,哪個更好?
- 10. GWT發生器得到編譯時間
- 11. 新發布的android應用程序的鏈接在哪裏?
- 12. 無法編譯鏈接列表程序
- 13. 鏈接錯誤「LogonUser」編譯C++程序?
- 14. 在D中編譯時間碼生成
- 15. Idoc的自定義程序編輯並重新發布到sap
- 16. 在應用程序中鏈接的自定義URL鏈接
- 17. 如何在tomcat中運行應用程序時重新鏈接鏈接錯誤?
- 18. 重新編譯iOS應用程序以在Apple Store上發佈
- 19. 在編譯時綁定重定向強命名程序集
- 20. 重新編譯二進制文件時發生總線錯誤
- 21. 在Java時間間隔定義中編譯C
- 22. 編譯Fortran和C++程序並從intel編譯器鏈接
- 23. 在編譯時鏈接vs在運行時鏈接到std ::庫
- 24. 在編譯時或鏈接時gcc的fvisibility
- 25. 編譯時錯誤:多重定義「主」
- 26. 如何在發生更新時重新啓動應用程序?
- 27. 編譯時間生成表
- 28. gcc明白編譯時間在哪裏
- 29. 新聞編輯鏈接沒有發生在gridview編輯模式
- 30. 生成自定義編譯時間警告C#
重新定義在鏈接階段發生。 – Ishmeet
是的,您可以覆蓋malloc(),因爲如果符號尚未被您自己的代碼滿足,鏈接器只會查看libc。通用建議:除非你真的*知道你在做什麼,否則不要試用。 – DevSolar