PRB: 链接错误LNK2005 在MFC库之前链接C运行时库导致的链接错误ID: Q148652
|
这篇文章适用于:
- Microsoft Visual C++, 32-bit Editions, versions 4.0, 4.1, 5.0, 6.0
SYMPTOMS 现象
当C运行时库(CRT)和MFC库以错误的顺序链接时,就会出现如下的LNK2005错误:
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(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)
mfcs40d.lib(dllmodul.obj): error LNK2005: _DllMain@12 already defined in
MSVCRTD.LIB (dllmain.obj)
mfcs42d.lib(dllmodul.obj): error LNK2005: _DllMain@12 already defined in
msvcrtd.lib(dllmain.obj)
CAUSE 原因
CRT库对new、delete和DllMain采用弱外部链接,而MFC库也包含了new、delete和DllMain函数,这就要求MFC库必须在CRT库之前被链接。
关于弱外部链接的更多信息,请参考下面微软知识库(Microsoft Knowledge Base)里的这篇文章:
Q72651 "Weak External" Records: Description, Use, and Errors
RESOLUTION 解决方案
目前有两种方法来解决这个问题。第一个方法采用强制链接器以正确顺序链接库文件。第二个方法允许你找出并纠正引起这个问题的模块。
方法一 - 强制链接器以正确顺序链接库文件
- 点击Project菜单中的Settings,打开项目设置对话框
- 在"Settings For:"下列框中选中出现链接错误的项目配置
- 点击Link页面
- 在Category组合框中选择INPUT
- 在"Libraries to Ignore"编辑框中输入库名(例如,Nafxcwd.lib Libcmtd.lib)
注: 等同于链接器命令行/NOD:<library name> - 在"Object/library Modules"编辑框中,输入库名。你必须确保列表中库的顺序,并且最前面的两个库为"Nafxcwd.lib Libcmtd.lib"
方法二 - 找出并纠正问题模块
通过下面步骤来查看当前库的链接顺序:
- 点击Project菜单中的Settings,打开项目设置对话框
- 在"Settings For:"下列框中选中出现这个链接错误的项目配置
- 点击Link页面
- 在Project Option框中输入:
/verbose:lib - 重新构造你的工程。在链接过程中,Output窗口将打印出库信息。
STATUS 状态
这些行为是正常的。
MORE INFORMATION 更多信息
当使用MFC库时,你必须确保它在CRT库之前被链接。这可以通过在工程的每个文件头上直接(#include <Afx.h>)或者间接(#include <Stdafx.h>)引用 "../Msdev/Mfc/Include/Afx.h"头文件来实现。Afx.h头文件通过使用预编译指令#pragma comment (lib,"<libname>") 强制纠正库顺序。
如果源文件是.c扩展名或者是.cpp扩展名但没有使用MFC,你可以创建一个小的头文件,然后在文件的头部引入。这个新的头文件将确保正确的库搜索顺序。
Visual C++没有包含这个头文件,但是你可以通过下面步骤轻易创建:
- 打开 ../Msdev/Mfc/Include/Afx.h文件。
- 选中第29行 (#ifndef _AFX_NOFORCE_LIBS) 到第204行 (#endif //!_AFX_NOFORCE_LIBS)的内容
- 复制选中的内容到Windows剪贴板
- 创建一个新的文本文件
- 粘贴剪贴板中的内容到新文件中
- 保存文件名为 ../Msdev/Mfc/Include/Forcelib.h