zz http://www.javaworld.com.tw/roller/qing/category/Win32
最近在VC 6.0上作業,有幾個地方都遇到一個十分惱人的錯誤。就是出現下述的錯誤:
Linking... nafxcwd.lib(afxmem.obj) : error LNK2005: "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(dbgdel.obj) Debug/DCap.exe : fatal error LNK1169: one or more multiply defined symbols found
這樣的錯誤,明顯就是兩個被link到的library都提供了同名的函式。但直接ignore掉LIBCMTD.lib當然是不行的,因為它是C的library。之所以發生這個問題,是因為MFC的library和C的library相衝突,必須設定它們被link的順序,也就是先nafxcwd.lib再LIBCMTD.lib。但是這二者都是default libraries,所以要怎麼設定它們的順序呢?我找到一個解法其實挺tricky的:先把它們分別都ignore掉,再額外將它們加入。也就是說:在Link頁籤上的Ignore Libraries輸入:nafxcwd.lib,libcmtd.lib,再到同一頁籤的Object/library modules輸入:nafxcwd.lib libcmtd.lib。這麼一來,加入它們的順序就成了我們所強迫設定的順序了。
http://www.acejoy.com/bbs/viewthread.php?tid=1065
//头文件主体
3.使用第三方的库造成的。这种情况主要是C运行期函数库和MFC的库冲突造成的。具体的办法就是将那个提示出错的库放到另外一个库的前面。另外选择不同的C函数库,可能会引起这个错误。微软和C有两种C运行期函数库,一种是普通的函数库:LIBC.LIB,不支持多线程。另外一种是支持多线程的:msvcrt.lib。如果一个工程里,这两种函数库混合使用,可能会引起这个错误,一般情况下它需要MFC的库先于C运行期函数库被链接,因此建议使用支持多线程的msvcrt.lib。所以在使用第三方的库之前首先要知道它链接的是什么库,否则就可能造成LNK2005错误。如果不得不使用第三方的库,可以尝试按下面所说的方法修改,但不能保证一定能解决问题,前两种方法是微软提供的:
A、选择VC菜单Project->Settings->Link->Catagory选择Input,再在Ignorelibraries 的Edit栏中填入你需要忽略的库,如:Nafxcwd.lib;Libcmtd.lib。然后在Object/libraryModules的Edit栏中填入正确的库的顺序,这里需要你能确定什么是正确的顺序,呵呵,God bless you!
B、选择VC菜单Project->Settings->Link页,然后在Project Options的Edit栏中输入/verbose:lib,这样就可以在编译链接程序过程中在输出窗口看到链接的顺序了。
C、选择VC菜单Project->Settings->C/C++页,Catagory选择Code Generation后再在User Runtime libraray中选择MultiThread DLL等其他库,逐一尝试。
关于编译器的相关处理过程,参考:
http://www.donews.net/xzwenlan/archive/2004/12/23/211668.aspx
http://www.cppblog.com/woaidongmao/archive/2010/02/18/108026.html
微软的解释
洋文:
CAUSE
The CRT libraries use weak external linkage for the new, delete, and DllMain fun...The CRT libraries use weak external linkage for the new, delete, and DllMain functions. The MFC libraries also contain new, delete, and DllMain functions. These functions require the MFC libraries to be linked before the CRT library is linked.
RESOLUTION
There are two ways to resolve this problem. The first solution involves forcing...There are two ways to resolve this problem. The first solution involves forcing the linker to link the libraries in the correct order. The second solution allows you to find the module that is causing the problem and to correct it.
Note The following steps are based on Visual C++ 6.0.
Solution One: Force Linker to Link Libraries in Correct Order
On the Project menu, click Settings.
In the Settings For view of the Project Settings dialog box, click to select the project configuration that is getting the link errors.
On the Link tab, click to select Input in the Category combo box.
In the Ignore libraries box, insert the library names (for example, Nafxcwd.lib;Libcmtd.lib).
Note The linker command-line equivalent in /NOD:<library name>.
In the Object/library modules box, insert the library names. You must make sure that these are listed in order and as the first two libraries in the line (for example, Nafxcwd.lib Libcmtd.lib).
To set this option in Visual C++ .NET, read the "Setting Visual C++ Project Properties" online help topic.
Solution Two: Locate and Correct the Problem Module
To view the current library link order, follow these steps:
On the Project menu, click Settings.
In the Settings For view of the Project Settings dialog box, click to select the project configuration that is getting the link errors.
On the Link tab, type /verbose:lib in the Project Options box.
Rebuild your project. The libraries will be listed in the output window during the linking process.
中文
原因
CRT 库对 new、delete 和 DllMain 函数使用弱外部链接。MFC 库也包含 new、delete 和 DllMain 函数。这些函数要求先链接...CRT 库对 new、delete 和 DllMain 函数使用弱外部链接。MFC 库也包含 new、delete 和 DllMain 函数。这些函数要求先链接 MFC 库,然后再链接 CRT 库。
解决方案
该问题有两种解决方法。
第一种方法是强制链接器按照正确的顺序链接库。
第二种方法是由您亲自查找导致问题的模块并纠正它。
注意:下列步骤基于 Visual C++ 6....该问题有两种解决方法。
第一种方法是强制链接器按照正确的顺序链接库。
第二种方法是由您亲自查找导致问题的模块并纠正它。
注意:下列步骤基于 Visual C++ 6.0 进行。
解决方案一:强制链接器按照正确的顺序链接库
在“项目”菜单上,单击“设置”。
在“项目设置”对话框的“以下项目的设置”视图中,单击以选中出现链接错误的项目配置。
在“链接”选项卡上,单击以选中“类别”组合框中的“输入”。
在“忽略库”框中,插入库名(例如,Nafxcwd.lib;Libcmtd.lib)。
注意:等效的链接器命令行是:/NOD:<library name>。
在“对象/库模块”框中,插入库名。必须确保这些库按顺序列出,而且是行中的前两个库(例如,Nafxcwd.lib 和 Libcmtd.lib)。
要在 Visual C++ .NET 中设置该选项,请阅读“设置 Visual C++ 项目属性”联机帮助主题。
解决方案二:找到并纠正出现问题的模块
要查看当前的库链接顺序,请按照下列步骤操作:
在“项目”菜单上,单击“设置”。
在“项目设置”对话框的“以下项目的设置”视图中,单击以选中出现链接错误的项目配置。
在“链接”选项卡上的“项目选项”框中键入 /verbose:lib。
重新生成项目。在链接过程中,这些库将在输出窗口中列出。
状态这种现象是设计导致的。这种现象是设计导致的。
更多信息
使用 MFC 库时,务必先链接它们,然后再链接 CRT 库。这可以通过确保项目中的每个文件都首先包含 Msdev/Mfc/Include/Afx.h 来完成。直...使用 MFC 库时,务必先链接它们,然后再链接 CRT 库。这可以通过确保项目中的每个文件都首先包含 Msdev/Mfc/Include/Afx.h 来完成。直接包含 (#include <Afx.h>) 或间接包含 (#include <Stdafx.h>) 都可以。Afx.h 包含文件会通过使用 #pragma comment (lib,"<libname>") 指令来强制采用库的正确顺序。
如果源文件的扩展名为 .c,或者该文件的扩展名为 .cpp 但不使用 MFC,则可以创建一个较小的头文件 (Forcelib.h) 并将其放在模块的顶端。这个新的头文件可确保按照正确的顺序搜索库。
Visual C++ 不包含该头文件。要创建此文件,请按照下列步骤操作:
打开 Msdev/Mfc/Include/Afx.h。
选定 #ifndef _AFX_NOFORCE_LIBS 和 #endif //!_AFX_NOFORCE_LIBS 之间的行。
将选定部分复制到 Windows 剪贴板。
创建一个新文本文件。
将剪贴板的内容粘贴到这个新文件中。
将该文件另存为 Msdev/Mfc/Include/Forcelib.h。
在 Visual C++ .NET 中重现问题的步骤
启动 Microsoft Visual Studio .NET。
在“文件”菜单上,指向“新建”,然后单击“项目”。
单击“项目类型”下的“Visual C++ 项目”,然后单击“模板”下的“MFC 应用程序”。
在“名称”文本框中,键入 Q148652。
在“位置”文本框中,键入 C:/Test,然后单击“确定”。
在“MFC 应用程序向导”对话框中,单击“应用程序类型”。
单击“应用程序类型”下的“基于对话框”,然后单击“MFC 的使用”下的“在静态库中使用 MFC”。
单击“完成”。
在“解决方案资源管理器”中,选择“源文件”下的全部三个 .cpp 文件。
右键单击三个选定的文件,然后单击“删除”。
右键单击“源文件”,指向“添加”,然后单击“添加新项”。
单击“模板”下的“C++ 文件”。在“名称”文本框中,键入 Aa。单击“打开”。
将以下代码粘贴到 Aa.cpp 中:
int test(){new int; return 1;}
右键单击“源文件”,指向“添加”,然后单击“添加现有项”。
选择以下文件:
Q148652.cpp
Q148652Dlg.cpp
stdafx.cpp
单击“打开”。
您在第 15 步中选择的文件将出现在“源文件”下。
选择“源文件”下的全部四个 .cpp 文件。
右键单击选定的四个 .cpp 文件,然后单击“属性”。
展开“配置属性”,然后展开“C/C++”。
单击“预编译头”。
将“创建/使用预编译头”属性设置为“不使用预编译头”。单击“确定”。
在“生成”菜单上,单击“重新生成解决方案”。