在 Visual C++ 中以錯(cuò)誤的順序鏈接 CRT 庫和 MFC 庫時(shí)出現(xiàn) LNK2005 錯(cuò)誤
癥狀
當(dāng) C 運(yùn)行時(shí) (CRT) 庫和 Microsoft 基礎(chǔ)類 (MFC) 庫的鏈接順序有誤時(shí),可能會(huì)出現(xiàn)以下 LNK2005 錯(cuò)誤之一:
nafxcwd.lib(afxmem.obj) :error LNK2005:
"void * __cdecl operator new(unsigned int)"(??2@YAPAXI@Z) already
defined in LIBCMTD.lib(new.obj)
"void * __cdecl operator new(unsigned int)"(??2@YAPAXI@Z) already
defined in LIBCMTD.lib(new.obj)
nafxcwd.lib(afxmem.obj) :error LNK2005:
"void __cdecl operator delete(void *)"(??3@YAXPAX@Z) already defined
in LIBCMTD.lib(dbgnew.obj)
"void __cdecl operator delete(void *)"(??3@YAXPAX@Z) already defined
in LIBCMTD.lib(dbgnew.obj)
nafxcwd.lib(afxmem.obj) :error LNK2005:
"void * __cdecl operator new(unsigned int,int,char const *,int)"
(??2@YAPAXIHPBDH@Z) already defined in LIBCMTD.lib(dbgnew.obj)
"void * __cdecl operator new(unsigned int,int,char const *,int)"
(??2@YAPAXIHPBDH@Z) already defined in LIBCMTD.lib(dbgnew.obj)
mfcs40d.lib(dllmodul.obj):error LNK2005:_DllMain@12 already defined in
MSVCRTD.LIB (dllmain.obj)
MSVCRTD.LIB (dllmain.obj)
mfcs42d.lib(dllmodul.obj):error LNK2005:_DllMain@12 already defined in
msvcrtd.lib(dllmain.obj)
msvcrtd.lib(dllmain.obj)
原因
CRT 庫對(duì) new、delete 和 DllMain 函數(shù)使用弱外部鏈接。MFC 庫也包含 new、delete 和 DllMain 函數(shù)。這些函數(shù)要求先鏈接 MFC 庫,然后再鏈接 CRT 庫。
解決方案
該問題有兩種解決方法。第一種方法是強(qiáng)制鏈接器按照正確的順序鏈接庫。第二種方法是由您親自查找導(dǎo)致問題的模塊并糾正它。
注意:下列步驟基于 Visual C++ 6.0 進(jìn)行。
要在 Visual C++ .NET 中設(shè)置該選項(xiàng),請(qǐng)閱讀“設(shè)置 Visual C++ 項(xiàng)目屬性”聯(lián)機(jī)幫助主題。
注意:下列步驟基于 Visual C++ 6.0 進(jìn)行。
解決方案一:強(qiáng)制鏈接器按照正確的順序鏈接庫
1. | 在“項(xiàng)目”菜單上,單擊“設(shè)置”。 |
2. | 在“項(xiàng)目設(shè)置”對(duì)話框的“以下項(xiàng)目的設(shè)置”視圖中,單擊以選中出現(xiàn)鏈接錯(cuò)誤的項(xiàng)目配置。 |
3. | 在“鏈接”選項(xiàng)卡上,單擊以選中“類別”組合框中的“輸入”。 |
4. | 在“忽略庫”框中,插入庫名(例如,Nafxcwd.lib;Libcmtd.lib)。 注意:等效的鏈接器命令行是:/NOD:<library name>。 |
5. | 在“對(duì)象/庫模塊”框中,插入庫名。必須確保這些庫按順序列出,而且是行中的前兩個(gè)庫(例如,Nafxcwd.lib 和 Libcmtd.lib)。 |
解決方案二:找到并糾正出現(xiàn)問題的模塊
要查看當(dāng)前的庫鏈接順序,請(qǐng)按照下列步驟操作:1. | 在“項(xiàng)目”菜單上,單擊“設(shè)置”。 |
2. | 在“項(xiàng)目設(shè)置”對(duì)話框的“以下項(xiàng)目的設(shè)置”視圖中,單擊以選中出現(xiàn)鏈接錯(cuò)誤的項(xiàng)目配置。 |
3. | 在“鏈接”選項(xiàng)卡上的“項(xiàng)目選項(xiàng)”框中鍵入 /verbose:lib。 |
4. | 重新生成項(xiàng)目。在鏈接過程中,這些庫將在輸出窗口中列出。 |
狀態(tài)
這種現(xiàn)象是設(shè)計(jì)導(dǎo)致的。
更多信息
使用 MFC 庫時(shí),務(wù)必先鏈接它們,然后再鏈接 CRT 庫。這可以通過確保項(xiàng)目中的每個(gè)文件都首先包含 Msdev\Mfc\Include\Afx.h 來完成。直接包含 (#include <Afx.h>) 或間接包含 (#include <Stdafx.h>) 都可以。Afx.h 包含文件會(huì)通過使用 #pragma comment (lib,"<libname>") 指令來強(qiáng)制采用庫的正確順序。
如果源文件的擴(kuò)展名為 .c,或者該文件的擴(kuò)展名為 .cpp 但不使用 MFC,則可以創(chuàng)建一個(gè)較小的頭文件 (Forcelib.h) 并將其放在模塊的頂端。這個(gè)新的頭文件可確保按照正確的順序搜索庫。
Visual C++ 不包含該頭文件。要?jiǎng)?chuàng)建此文件,請(qǐng)按照下列步驟操作:
如果源文件的擴(kuò)展名為 .c,或者該文件的擴(kuò)展名為 .cpp 但不使用 MFC,則可以創(chuàng)建一個(gè)較小的頭文件 (Forcelib.h) 并將其放在模塊的頂端。這個(gè)新的頭文件可確保按照正確的順序搜索庫。
Visual C++ 不包含該頭文件。要?jiǎng)?chuàng)建此文件,請(qǐng)按照下列步驟操作:
1. | 打開 Msdev\Mfc\Include\Afx.h。 |
2. | 選定 #ifndef _AFX_NOFORCE_LIBS 和 #endif //!_AFX_NOFORCE_LIBS 之間的行。 |
3. | 將選定部分復(fù)制到 Windows 剪貼板。 |
4. | 創(chuàng)建一個(gè)新文本文件。 |
5. | 將剪貼板的內(nèi)容粘貼到這個(gè)新文件中。 |
6. | 將該文件另存為 Msdev\Mfc\Include\Forcelib.h。 |
在 Visual C++ .NET 中重現(xiàn)問題的步驟
1. | 啟動(dòng) Microsoft Visual Studio .NET。 | ||||||
2. | 在“文件”菜單上,指向“新建”,然后單擊“項(xiàng)目”。 | ||||||
3. | 單擊“項(xiàng)目類型”下的“Visual C++ 項(xiàng)目”,然后單擊“模板”下的“MFC 應(yīng)用程序”。 | ||||||
4. | 在“名稱”文本框中,鍵入 Q148652。 | ||||||
5. | 在“位置”文本框中,鍵入 C:\Test,然后單擊“確定”。 | ||||||
6. | 在“MFC 應(yīng)用程序向?qū)?#8221;對(duì)話框中,單擊“應(yīng)用程序類型”。 | ||||||
7. | 單擊“應(yīng)用程序類型”下的“基于對(duì)話框”,然后單擊“MFC 的使用”下的“在靜態(tài)庫中使用 MFC”。 | ||||||
8. | 單擊“完成”。 | ||||||
9. | 在“解決方案資源管理器”中,選擇“源文件”下的全部三個(gè) .cpp 文件。 | ||||||
10. | 右鍵單擊三個(gè)選定的文件,然后單擊“刪除”。 | ||||||
11. | 右鍵單擊“源文件”,指向“添加”,然后單擊“添加新項(xiàng)”。 | ||||||
12. | 單擊“模板”下的“C++ 文件”。在“名稱”文本框中,鍵入 Aa。單擊“打開”。 | ||||||
13. | 將以下代碼粘貼到 Aa.cpp 中:
|
||||||
14. | 右鍵單擊“源文件”,指向“添加”,然后單擊“添加現(xiàn)有項(xiàng)”。 | ||||||
15. | 選擇以下文件:
|
||||||
16. | 單擊“打開”。 | ||||||
17. | 您在第 15 步中選擇的文件將出現(xiàn)在“源文件”下。 | ||||||
18. | 選擇“源文件”下的全部四個(gè) .cpp 文件。 | ||||||
19. | 右鍵單擊選定的四個(gè) .cpp 文件,然后單擊“屬性”。 | ||||||
20. | 展開“配置屬性”,然后展開“C/C++”。 | ||||||
21. | 單擊“預(yù)編譯頭”。 | ||||||
22. | 將“創(chuàng)建/使用預(yù)編譯頭”屬性設(shè)置為“不使用預(yù)編譯頭”。單擊“確定”。 | ||||||
23. | 在“生成”菜單上,單擊“重新生成解決方案”。 |
posted on 2007-09-21 18:39 大龍 閱讀(594) 評(píng)論(0) 編輯 收藏 引用