静态链接和动态链接库混用导致的链接错误LINK2005

简介:

   对于一个静态链接库L.lib,它的使用者app.exe会静态链接L.lib,意思是app.exe会将L.lib中的代码(app需要的部分,例如函数定义,类的定义等等)链接到app.exe中.

  而对于L.lib本身来说,它的CRT(C Run-Time Libraries)有多种配置,这里仅考虑/MTd.如果配置为/MTd,L.lib会链接静态库libcmtd.lib,这意味着会将libcmtd.lib中的代码(L.lib需要的部分,例如函数定义,类的定义等等)链接到L.lib中.为了更清楚说明问题,下面举一个例子.

L.lib中有文件L.h和L.cpp,L.h的内容(部分)如下:
#param once
#include <string>
void testfun();

L.cpp中的内容(部分)如下:
std::basic_string<char> g_teststring("aaaaaaaaaa");
vod testfun(){
//使用了标准静态库libcmtd.lib中的类,会将std::basic_string<char>定义代码复制到该模块中.
    std::basic_string<char> str(g_teststr);
}

Build之后生成L.lib,然后以二进制方式打开L.obj,可以看到如下内容:
...std::basic_string<char,std::char_traits<char>,std::allocator<char> >...
很明显,L.obj包含有std::basic_string<char>的定义,这才是静态链接的含义.那么这会有什么问题呢?

  现在假设一种情况,E.exe的CRT配置为/MDd,这意味着它会动态链接msvcrtd.lib,同时E.exe也链接到L.lib,假如该工程中有一个文件E.CPP,它的内容如下:
#include "L.h"
#include <string>
testfun();//来自于L.lib的头文件L.h
std::string<char> g_teststdstring("bbbbbbbbbb"); //A

  Build该工程,就会发生LINK2005的错误:
msvcprtd.lib(MSVCP90D.dll): error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in L.lib(L.obj)
  这个错误很明显指出,std::basic_string<char>重复定义,这是因为E.cpp在同时使用了L.lib和msvcrtd.lib,编译完成后,E.obj会链接L.lib和msvcrtd.lib时,此时发现在这两个库中都有std::basic_string<char>的定义,这显然是不允许的.

  如果将E.cpp中的A行代码改为:
std::string<TCHAR> g_teststdstring(_T("bbbbbbbb"));
就不会有链接错误LINK2005了.

  需要注意的是,如果E.cpp中出现关于vector的变量的定义,同样会出现LINK2005链接错误,即使你没有使用std::basic_string.这说明只要你在工程E.exe中同时使用了动态标准链接库和静态链接标准库,就有可能出现标准库中某些类型重复定义的错误.

现在你应该彻底理解了LIN2005的错误了,问题的根源已经找到,解决办法自己应该能想到了吧.

 














本文转自jetyi51CTO博客,原文链接:http://blog.51cto.com/jetyi/785974 ,如需转载请自行联系原作者






相关文章
|
6月前
|
Ubuntu 网络安全 C语言
vscode 编译多个当前目录下cpp文件,报错未定义标识符的问题
vscode 编译多个当前目录下cpp文件,报错未定义标识符的问题
377 0
|
6月前
|
存储 编译器 程序员
【新手解答1】深入探索 C 语言:变量名、形参 + 主调函数、被调函数 + 类和对象 + 源文件(.c 文件)、头文件(.h 文件)+ 库
【新手解答1】深入探索 C 语言:变量名、形参 + 主调函数、被调函数 + 类和对象 + 源文件(.c 文件)、头文件(.h 文件)+ 库
135 0
|
存储 Cloud Native Linux
C++ 动态库与静态库的区别?
C++ 动态库与静态库的区别?
|
Linux API C语言
编译参数中如何包含头文件和动态链接库
GCC编译参数:如何包含头文件和动态链接库
69 0
|
芯片 C++
【MDK(keil)编译错误】找不到main.o及解决方法、多处报错“未定义”
【MDK(keil)编译错误】找不到main.o及解决方法、多处报错“未定义”
1139 0
【MDK(keil)编译错误】找不到main.o及解决方法、多处报错“未定义”
编译lua5.3.5报错:libreadline.so存在多处未定义的引用
编译lua5.3.5报错:libreadline.so存在多处未定义的引用
105 0
玩转Makefile | 编译有共用文件的多个程序
玩转Makefile | 编译有共用文件的多个程序
289 0
玩转Makefile | 编译有共用文件的多个程序
C++编译提示宏重定义了,怎么办?
C++编译提示宏重定义了,怎么办?
941 0