連結器工具錯誤 LNK2005
對象中已經定義的符號
符號 符號 已定義多次。
此錯誤後面接著嚴重錯誤 LNK1169。
多個原因與解決方案
一般而言,此錯誤表示您已中斷 一個定義規則,這隻允許指定物件檔案中任何已使用之範本、函式、類型或對象的定義,以及針對外部可見物件或函式,在整個可執行檔中只允許一個定義。
以下是此錯誤的一些常見原因。
當頭檔案定義變數時,可能會發生此錯誤。 例如,如果您在專案中的多個原始程式檔中包含此標頭檔,則會產生錯誤:
// LNK2005_global.h int global_int; // LNK2005
可能的解決方案包括:
宣告頭檔中的變數
extern
:extern int global_int;
,然後定義變數,並選擇性地在一個原始程式檔中初始化它:int global_int = 17;
。 此變數現在是全域變數,您可以在任何原始程序檔中宣告它extern
,例如,包含頭檔。 針對必須是全域的變數,我們建議此解決方案,但良好的軟體工程實務會將全域變數降到最低。宣告變數 靜態:
static int static_int = 17;
。 這會將定義的範圍限制為目前的物件檔,並允許多個物件檔案有自己的變數複本。 我們不建議您在頭檔中定義靜態變數,因為可能會混淆全域變數。 偏好將靜態變數定義移至使用它們的原始程序檔。宣告變數 selectany:
__declspec(selectany) int global_int = 17;
。 這會告訴連結器挑選一個定義供所有外部參考使用,並捨棄其餘部分。 結合匯入連結庫時,此解決方案有時很有用。 否則,我們不建議將其作為避免鏈接器錯誤的一種方式。
當頭檔定義不是
inline
的函式時,就會發生此錯誤。 如果您在多個原始程式檔中包含此頭檔,您會在可執行檔中取得函式的多個定義。// LNK2005_func.h int sample_function(int k) { return 42 * (k % 167); } // LNK2005
可能的解決方案包括:
將
inline
關鍵字新增至函式:// LNK2005_func_inline.h inline int sample_function(int k) { return 42 * (k % 167); }
從標頭檔中移除函式主體,只保留宣告,然後在一個和只有一個原始程式檔中實作函式:
// LNK2005_func_decl.h int sample_function(int);
// LNK2005_func_impl.cpp int sample_function(int k) { return 42 * (k % 167); }
如果您在標頭檔案中定義類別宣告以外的成員函式,也可能會發生此錯誤:
// LNK2005_member_outside.h class Sample { public: int sample_function(int); }; int Sample::sample_function(int k) { return 42 * (k % 167); } // LNK2005
若要修正此問題,請在 類別內移動成員函式定義。 類別宣告內定義的成員函式會隱含內嵌。
// LNK2005_member_inline.h class Sample { public: int sample_function(int k) { return 42 * (k % 167); } };
如果您連結一個以上的標準連結庫或CRT版本,就可能發生此錯誤。 例如,如果您嘗試將零售和偵錯 CRT 連結庫,或連結庫的靜態和動態版本,或兩個不同的標準連結庫版本連結到可執行檔,可能會回報此錯誤多次。 若要修正此問題,請從連結命令中移除每個連結庫的所有複本。 我們不建議您在相同的可執行檔中混合零售和偵錯連結庫,或不同版本的連結庫。
若要告訴連結器使用預設值以外的連結庫,請在命令行上指定要使用的連結庫,並使用 /NODEFAULTLIB 選項來停用默認連結庫。 在 IDE 中,新增項目的參考以指定要使用的連結庫,然後開啟專案的 [屬性頁] 對話框,然後在 [鏈接器] 的 [輸入] 屬性頁中,設定 [忽略所有默認連結庫] 或 [忽略特定默認連結庫] 屬性來停用默認連結庫。
如果您在使用 /clr 選項時混合使用靜態和動態連結庫,就會發生此錯誤。 例如,如果您建置 DLL 以用於靜態 CRT 中連結的可執行檔中,就可能發生此錯誤。 若要修正此問題,請只針對整個可執行檔使用靜態連結庫或動態連結庫,以及您建置以用於可執行檔中的任何連結庫。
如果符號是封裝函式(使用 /Gy 編譯所建立),而且包含在多個檔案中,但在編譯之間已變更,就可能發生此錯誤。 若要修正此問題,請重新編譯包含已封裝函式的所有檔案。
如果在不同連結庫中的兩個成員物件中以不同的方式定義符號,而且會使用這兩個成員物件,就會發生此錯誤。 當連結庫以靜態方式連結時,修正此問題的其中一種方法是只使用一個連結庫的成員物件,並在連結器命令行上先包含該連結庫。 若要使用這兩個符號,您必須建立區分符號的方式。 例如,如果您可以從來源建置連結庫,您可以將每個連結庫包裝在唯一的命名空間中。 或者,您可以建立新的包裝函式連結庫,使用唯一名稱來包裝其中一個原始連結庫的參考、將新連結庫連結到原始連結庫,然後將可執行文件連結至新的連結庫,而不是原始連結庫。
如果
extern const
變數定義兩次,而且每個定義中都有不同的值,就會發生此錯誤。 若要修正此問題,請只定義一次常數,或使用命名空間或enum class
定義來區分常數。如果您使用 uuid.lib 與其他定義 GUID 的 .lib 檔案組合,就會發生此錯誤(例如 oledb.lib 和 adsiid.lib)。 例如:
oledb.lib(oledb_i.obj) : error LNK2005: _IID_ITransactionObject already defined in uuid.lib(go7.obj)
若要修正此問題,請將 /FORCE:MULTIPLE 新增至連結器命令行選項,並確定 uuid.lib 是第一個參考的連結庫。