• [转]visual studio运行时库MT、MTd、MD、MDd的研究


    原文地址

    在开发window程序是经常会遇到编译好好的程序拿到另一台机器上面无法运行的情况,这一般是由于另一台机器上面没有安装相应的运行时库导致的,那么这个与编译选项MT、MTd、MD、MDd有什么关系呢?这是msdn上面的解释:

    MT:mutithread,多线程库,编译器会从运行时库里面选择多线程静态连接库来解释程序中的代码,即连接LIBCMT.lib库

    MTd:mutithread+debug,多线程调试版,连接LIBMITD.lib库

    MD:MT+DLL,多线程动态库,连接MSVCRT.lib库,这是个导入库,对应动态库为MSVCRT.dll

    MDd: MT+DLL+debug,多线程动态调试库,连接MSVCRTD.lib库,对应动态库为MSVCRTD.dll

    开发多线程程序时(单线程本文不做讨论),需要选择MT、MTd、MD、MDd其中的一个。

    对于MT/MTd,由于连接运行时库是LIBCMT.lib/LIBCMTD.lib,这两个库是静态库,所以此种方式编译的程序,移到另一台机器上面也可以正常运行。

    但是对于MD/MDd,连接的是动态库,所以如果另一台机器上没有MSVCRT.dll/MSVCRTD.dll时,就提示缺少动态库这样的错误。

    曾经犯这样的错误,以为以MT/MTd方式编译,程序对所有的库都是静态链接的,其实错了,它只能决定运行时库是动态链接还是静态链接,对用户自己写的库或其他第三方库,其连接方式取决于代码(显式连接动态库Loadlibrary)或所提供的lib文件(为导入库还是静态库),移动程序到别的机器上时,还是要带上所需要的动态库的。

    来看一个例子,编译一个静态库和一个动态库,均实现两个整数相加的功能:

    [cpp] view plain copy
     
    1. // adds.h  
    2. // add后面加个s代表静态库  
    3. #pragma once  
    4. int add(int,int);  
    [cpp] view plain copy
     
    1. // adds.cpp  
    2. // 静态库  
    3. #include "adds.h"  
    4. int add(int a, int b)  
    5. {  
    6.     return a+b;  
    7. }  
    8. 以上,运行时库选择MTd,编译成静态库adds.lib  
    [cpp] view plain copy
     
    1.    
    [cpp] view plain copy
     
    1. // addd.h  
    2. // add后面加d代表动态库  
    3. #pragma once  
    4. #ifndef MYLIB_API  
    5. #define MYLIB_API _declspec(dllexport)  
    6. #endif  
    7.   
    8. MYLIB_API int  add(int,int);  
    [cpp] view plain copy
     
    1. // addd.cpp  
    2. // 动态库  
    3. #include "addd.h"  
    4. int add(int a, int b)  
    5. {  
    6.   return a+b;  
    7. }以上,运行时库选择MTd,编译成动态库addd.lib, addd.dll  
    [cpp] view plain copy
     
    1. // test.cpp  
    2. // 测试程序  
    3. #include <iostream>  
    4.   
    5. // 测试静态库,此处为1,测试动态库,此处为0  
    6. #define TEST_STATIC_LINK 1  
    7.   
    8. #if TEST_STATIC_LINK   
    9.   #include <adds.h>  
    10. #else  
    11.   #define MYLIB_API _declspec(dllimport)  
    12.   #include "addd.h"  
    13. #endif  
    14.   
    15. using namespace std;  
    16.   
    17. int main()  
    18. {  
    19.     cout << add(2,3) << endl;  
    20.     return 0;  
    21. }测试程序以MTd编译  

    1. 测试静态库,TEST_STATIC_LINK 定义为1,提供adds.lib,生成可执行文件,移动到另一台机器上可以运行,因为测试程序和adds.lib均静态连接运行时库

    2. 测试动态库,TEST_STATIC_LINK 定义为0,提供addd.lib,生成可执行文件,移动到另一台机器上可以运行,但需要addd.dll,因为addd库静态连接运行时库,测试程序静态连接运行时库,动态连接addd库

    在上面的例子中add库和测试程序均选择MTd运行时库,若不一致会导致一些编译连接错误,让新手不着头脑。

    比如adds选择MDd,连接将会出现这样的错误:

    1>正在链接...

    1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) 已经在LIBCMTD.lib(typinfo.obj) 中定义

    1>MSVCRTD.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) 已经在LIBCMTD.lib(typinfo.obj) 中定义

    即一个程序中混合了不同的运行时库(静态库和动态库,调试库和非调试库),可能会产生冲突,所以一个程序中应该使用相同的运行时库。

    引用资料:

    http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=vs.71).aspx

  • 相关阅读:
    只需5分钟就能Get到的神器:Python虚拟环境安装&使用
    Linux——28年桌面进化史
    Linux使用Pidstat命令查看进程状态信息
    提高思维能力的书籍推荐你看这本《决策必读12篇》
    管理和自我管理:领导者自我管理的重要性
    带团队看什么书 ?这本书教你提升团队凝聚力
    基于RNN和CTC的语音识别模型,探索语境偏移解决之道
    详解Spring中Bean的作用域与生命周期
    物联网通信技术,那些你不知道的事
    一招教你数据仓库如何高效批量导入与更新数据
  • 原文地址:https://www.cnblogs.com/ld1226/p/8670224.html
Copyright © 2020-2023  润新知