关于动态链接库编译顺序导致 " _DllMain@12 已经在 LIBCMTD.lib(dllmain.obj) 中定义 " 问题的解决方法

dengniancai 2008-10-16 03:13:29
1. 我用 VC 2003 编译一个关于网络发包的动态链接库, 其中包含文件如下:

- 源文件
- base64.cpp
- CWSTAPI.cpp
- IniFile.cpp
- md5.cpp
- 头文件
- base64.h
- CWSTAPI.h
- IniFile.h
- md5.h

其中 CWSTAPI.h 和 CWSTAPI.cpp 文件中包含动态链接库导出函数的声明和定义.

2. 直接生成解决方案会产生如下错误 :
LINK : LNK6004: 没有找到 ..\..\bin/CWSTAPI.dll 或上一个增量链接没有生成它;正在执行完全链接
nafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 已经在 LIBCMTD.lib(dllmain.obj) 中定义
nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 libcpmtd.lib(newop.obj) 中定义
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) 已经在 LIBCMTD.lib(dbgdel.obj) 中定义
nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) 已经在 libcpmtd.lib(newaop.obj) 中定义
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) 已经在 LIBCMTD.lib(delete2.obj) 中定义
nafxcwd.lib(dllmodul.obj) : warning LNK4006: _DllMain@12 已在 LIBCMTD.lib(dllmain.obj) 中定义;已忽略第二个定义
nafxcwd.lib(afxmem.obj) : warning LNK4006: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已在 libcpmtd.lib(newop.obj) 中定义;已忽略第二个定义
nafxcwd.lib(afxmem.obj) : warning LNK4006: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) 已在 LIBCMTD.lib(dbgdel.obj) 中定义;已忽略第二个定义
nafxcwd.lib(afxmem.obj) : warning LNK4006: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) 已在 libcpmtd.lib(newaop.obj) 中定义;已忽略第二个定义
nafxcwd.lib(afxmem.obj) : warning LNK4006: "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) 已在 LIBCMTD.lib(delete2.obj) 中定义;已忽略第二个定义
正在创建库 ..\..\bin/CWSTAPI.lib 和对象 ..\..\bin/CWSTAPI.exp
..\..\bin/CWSTAPI.dll : fatal error LNK1169: 找到一个或多个多重定义的符号

后来发现 .cpp 文件的编译顺序如下:

正在编译...
md5.cpp
IniFile.cpp
CWSTAPI.cpp
base64.cpp

3. 以前我没有添加 base64.h 和 base64.cpp 文件, 可以正常编译, 难道是和这个有关, 于是我想办法让 base64.cpp 在 CWSTAPI.cpp 之前编译, 我共想了三种方法 :
(1) 先将 base64.cpp 文件从项目中移除, 接着又加载进来, 那么 "解决方案资源管理器" 中文件的顺序为 :

- 源文件
- CWSTAPI.cpp
- IniFile.cpp
- md5.cpp
- base64.cpp

这样我点击菜单上 生成 -> 重新生成解决方案, 果然编译顺序为 :

正在编译...
base64.cpp
md5.cpp
IniFile.cpp
CWSTAPI.cpp

注意不能使用生成解决方案, 那样可能 .cpp 文件不会重新编译.

但是这样会发生问题, 因为你关掉这个解决方案, 重新打开这个解决方案时, 文件又按字母顺序在 "解决方案资源管理器" 中显示, 这就以为着生成解决方案编译 .cpp 文件时是按照 .cpp 文件的字母顺序来编译的.

(2) 重命名 .cpp 文件的名称
既然 .cpp 文件是根据字母顺序排序的, 编译时也遵循这个顺序的反序, 那么只要保证 CWSTAPI.cpp 文件最后编译就可以了, 而 base64.cpp 文件排在 CWSTAPI.cpp 文件的前面, 那么将 base64.cpp 文件重命名为 ZBase64.cpp, 并相应地将 base64.h 重命名为 ZBase64.h, 这样就改变了编译的顺序. 这样做有个不好的地方就是为了达到调整编译顺序的目的而去改变 .cpp 文件的名称, 这样的命名往往是违心的.

(3) 将 .cpp 移到其他文件夹中
VC 默认将 .cpp 文件放在 源文件中, 将 .h 文件放在 头文件中.
建立一个文件夹 Include, 将除了 CWSTAPI.h, CWSTAPI.cpp 文件的所有 .h 和 .cpp 文件都放在这个文件夹中, 即

- 源文件
- CWSTAPI.cpp
- 头文件
- CWSTAPI.h
- 资源文件
- Include
- base64.cpp
- base64.h
- IniFile.cpp
- IniFile.h
- md5.cpp
- md5.h

这个顺序需要重新打开解决方案才能看到, 这样编译顺序为 :

正在编译...
md5.cpp
IniFile.cpp
base64.cpp
CWSTAPI.cpp

4. 这个问题足足困扰了我大半天, 最后终于找到这几种解决方法, 并且分享给大家, 最终我采用了最后一种方法. 这些方法肯定不是最好的, 所以我想征集一下大家的方法.
...全文
2804 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
地球网事 2012-04-09
  • 打赏
  • 举报
回复
直接修改.vcproj,把base64.cpp和base64.h放最后面,就好了,我的老天。
  • 打赏
  • 举报
回复
狂顶楼主。太有才了。这个问题困扰我了很久,调单线程为多线程,也不能解决。一试楼主的方法,立竿见影。很好。希望大家也都多留意其他解决办法,都分享一下。
HyperZero 2009-05-14
  • 打赏
  • 举报
回复
还有一个,如果在ocx工程中使用CString也会触发2005错误,只能使用其他类型
kelvin_2013 2008-11-02
  • 打赏
  • 举报
回复
mark
dengniancai 2008-10-18
  • 打赏
  • 举报
回复
第一次发帖, 给大家都送分啊.
djd7726 2008-10-18
  • 打赏
  • 举报
回复
写得太多,没看仔细.我刚遇到过类似问题.链接时出错,再链接一遍.就可以.原因是在".h"中定义全局变量引起的.将这个全局变量放到类中.好像用extern也可以.
K行天下 2008-10-18
  • 打赏
  • 举报
回复
赞!
yangkunjie 2008-10-18
  • 打赏
  • 举报
回复
解决了问题就行,如果是我,我首先想到的肯定是第2种解决办法,不过我倾向于最后一种解决办法
yangkunjie 2008-10-18
  • 打赏
  • 举报
回复
先告诉你怎么加分,再看题,第二天可以给帖子加分,并且限制只能加100分
boys2002 2008-10-18
  • 打赏
  • 举报
回复
重命名



顶下先



有点累了


先 沙发一会~~~~~~~~~~~~~~·
dengniancai 2008-10-18
  • 打赏
  • 举报
回复
怎么加分啊?
hityct1 2008-10-17
  • 打赏
  • 举报
回复
kevin0716 2008-10-16
  • 打赏
  • 举报
回复
up
帅得不敢出门 2008-10-16
  • 打赏
  • 举报
回复
up
JJZHK 2008-10-16
  • 打赏
  • 举报
回复
我基本上也是换文件名、位置,希望找到更好的方法。
UP.
xkyx_cn 2008-10-16
  • 打赏
  • 举报
回复
顶楼主

64,653

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧