首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

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

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

关于动态链接库编译顺序导致 " _DllMain@12 已经在 LIBCMTD.lib(dllmain.obj) 中定义 " 问题的解决方法
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. 这个问题足足困扰了我大半天, 最后终于找到这几种解决方法, 并且分享给大家, 最终我采用了最后一种方法. 这些方法肯定不是最好的, 所以我想征集一下大家的方法.

[解决办法]
顶楼主
[解决办法]
我基本上也是换文件名、位置,希望找到更好的方法。
UP.
[解决办法]
up
[解决办法]
up

[解决办法]

[解决办法]
重命名



顶下先 



有点累了


先 沙发一会~~~~~~~~~~~~~~·
[解决办法]
先告诉你怎么加分,再看题,第二天可以给帖子加分,并且限制只能加100分
[解决办法]
解决了问题就行,如果是我,我首先想到的肯定是第2种解决办法,不过我倾向于最后一种解决办法
[解决办法]
赞!
[解决办法]
写得太多,没看仔细.我刚遇到过类似问题.链接时出错,再链接一遍.就可以.原因是在".h"中定义全局变量引起的.将这个全局变量放到类中.好像用extern也可以.

热点排行