#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其中的一个。
为了提高C语言的开发效率,C标准定义了一系列常用的函数,称为C库函数。C标准仅仅定义了函数原型,并没有提供实现。因此这个任务留给了各个支持C语言标准的编译器。每个编译器通常实现了标准C的超集,称为C运行时库(C Run Time Libray) ,简称CRT。对于VC++编译器来说,它提供的CRT库支持C标准定义的标准C函数,同时也有一些专门针对windows系统特别设计的函数。
与C语言类似,C++也定义了自己的标准,同时提供相关支持库,我们把它称为C++运行时库或C++标准库。
由于C++对C的兼容性,C++标准库包括了C标准库,除此之外还包括IO流和标准模板库STL。
VC++在何处实现C和C++运行库,VC++完美的支持C和C++标准,因此也就按照C和C++的标准定义的函数原型实现了上述运行时库。为了方便有不同需求的客户的使用,VC++分别实现了动态链接库DLL版本和静态库LIB版本。同时为了支持程序调试且不影响程序的性能,又分别提供了对应的调试版本。调试版本的名称在Release版本名称后添了字母d。
对于C运行时库CRT,VC6.0、VC2005、VC2008和VC2010均提供了DLL版本和LIB版本。上述各个编译器提供的LIB版的CRT库,均实现在libcmt.lib。对应的调试版名称为libcmtd.lib。
而DLL版本名称根据编译器不同而不同,我们可以从名称上加以分辨。
- VC6.使用的CRT库的DLL版本在MSVCRT.DLL中实现, 对应调试版本为MSVCRTD.LIB。
- VC2005使用的CRT库的DLL版本在MSVCR80.DLL中实现,对应调试版本为MSVCR80.DLL。
- VC2008使用的CRT库的DLL版本在MSVCR90.DLL中实现,对应调试版本为MSVCR90D.DLL。
- VC2010使用的CRT库的DLL版本在MSVCR100.DLL中实现,对应调试版本为MSVCR100D.DLL。
C++标准兼容C标准,但VC各版本将C++编译器使用的C标准库与C编译器使用的C运行库一起实现,它们使用相同的运行库。对于C++标准库中的IO流和STL,VC6.0、VC2005、VC2008和VC2010也提供了DLL版本和LIB版本。LIB版均实现在libcpmt.lib中,对应的调试版本为libcpmtd.lib。
不同版本的编译器实现的DLL也不相同。
- VC6.使用的C++类库的 DLL版本在MSVCP60.DLL中实现, 对应调试版本为MSVCP60D.LIB。
- VC2005使用的C++类库的DLL版本在MSVCP80.DLL中实现,对应调试版本为MSVCP80.DLL。
- VC2008使用的C++类库的 DLL版本在MSVCP90.DLL中实现,对应调试版本为MSVCP90D.DLL。
- VC2010使用的C++类库的DLL版本在MSVCP100.DLL中实现,对应调试版本为MSVCP100D.DLL。
在各个版本的编译器中,我们可以通过配置选项来设置程序使用的C和C++运行时库的类型。如下图(其他版本编译器大同小异):
- MT选项:链接LIB版的C和C++运行库。在链接时就会在将C和C++运行时库集成到程序中成为程序中的代码,程序体积会变大。
- MTd选项:LIB的调试版。
- MD选项:使用DLL版的C和C++运行库,这样在程序运行时会动态的加载对应的DLL,程序体积会减小,缺点是在系统没有对应DLL时程序无法运行。
- MDd选项:表示使用DLL的调试版。
对于MT/MTd,由于连接运行时库是LIBCMT.lib/LIBCMTD.lib,这两个库是静态库,所以此种方式编译的程序,移到另一台机器上面也可以正常运行。
但是对于MD/MDd,连接的是动态库,所以如果另一台机器上没有MSVCRT.dll/MSVCRTD.dll时,就提示缺少动态库这样的错误。
动态版(DLL)和静态版(LIB)C和C++运行库的优缺点
因为静态版必须把C和C++运行库复制到目标程序中,所以产生的可执行文件会比较大。同时对于使用多个模块的大型软件来说,如果每个模块均选择静态链接C或C++运行库,在程序运行时就会存在多个运行库。在链接时也会出现重复定义的问题。
使用DLL版的C和C++运行库,程序在运行时动态的加载对应的DLL。程序体积变小,但一个很大的问题就是一旦找不到对应DLL,程序将无法运行。假设使用VC6.0并选择使用MD选项构建,那么当用户使用VC2005来使用这个DLL时很可能出现找不到MSVCRT.DLL或MSVCP60.DLL的情况。
犯这样的错误,以为以MT/MTd方式编译,程序对所有的库都是静态链接的,其实错了,它只能决定运行时库是动态链接还是静态链接,对用户自己写的库或其他第三方库,其连接方式取决于代码(显式连接动态库Loadlibrary)或所提供的lib文件(为导入库还是静态库),移动程序到别的机器上时,还是要带上所需要的动态库的。
来看一个例子,编译一个静态库和一个动态库,均实现两个整数相加的功能:
// adds.h
// add后面加个s代表静态库
#pragma once
int add(int,int);
// adds.cpp
// 静态库
#include "adds.h"
int add(int a, int b)
{return a+b;
}
以上,运行时库选择MTd,编译成静态库adds.lib
// addd.h
// add后面加d代表动态库
#pragma once
#ifndef MYLIB_API
#define MYLIB_API _declspec(dllexport)
#endifMYLIB_API int add(int,int);
// addd.cpp
// 动态库
#include "addd.h"
int add(int a, int b)
{return a+b;
}
以上,运行时库选择MTd,编译成动态库addd.lib, addd.dll
// test.cpp
// 测试程序
#include <iostream>// 测试静态库,此处为1,测试动态库,此处为0
#define TEST_STATIC_LINK 1#if TEST_STATIC_LINK #include <adds.h>
#else#define MYLIB_API _declspec(dllimport)#include "addd.h"
#endifusing namespace std;int main()
{cout << add(2,3) << endl;return 0;
}
测试程序以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) 中定义
即一个程序中混合了不同的运行时库(静态库和动态库,调试库和非调试库),可能会产生冲突,所以一个程序中应该使用相同的运行时库。
#visual studio# 运行库MT、MTd、MD、MDd相关推荐
- vs编译c语言停止工作运行库mt,vc++编译时运行库选择(/MT/MTd/MD/MDd)
vc++编译时运行库选择(/MT/MTd/MD/MDd) vc++编译时运行库选择(/MT./MTd./MD./MDd) 在vs中,项目属性 ->C/C++ ->代码生成 ->运行库 ...
- VC编译选项 /ML /MLd /MT /MTd /MD /MDd之间的区别
VC编译选项 /ML /MLd /MT /MTd /MD /MDd之间的区别 VC编译选项 多线程(/MT) 多线程调试(/MTd) 多线程 DLL (/MD) 多线程调试 DLL (/MDd) C ...
- CMake设置MSVC工程MT/MTd/MD/MDd
文章目录 0. 前言 1. 如何设置 1.1 CMakeLists代码 1.2 要点1:POLICY 1.3 要点2:set_property 0. 前言 在MSVC工程上右键->属性,找到配置 ...
- 各个版本Microsoft Visual C++运行库下载
原文:各个版本Microsoft Visual C++运行库下载 作者:慕容雪_ 一个很好的合计, 转载备份一份 各个版本Microsoft Visual C++运行库下载 Microsoft Vis ...
- 【转载】各个版本Microsoft Visual C++运行库下载
原文:各个版本Microsoft Visual C++运行库下载 作者:慕容雪_ 一个很好的合计, 转载备份一份 各个版本Microsoft Visual C++运行库下载 Microsoft Vis ...
- 解决方案-Visual Studio生成库(DLLLIB)以及如何调用
作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 问题说明 使用VS编程时,一般会根据不同的场景需求将类封装成库文件,以供他人使用,比如我作为算法 ...
- 微软运行库合集_Microsoft Visual C++ 运行库合集_解决Unable to load JVM问题
Microsoft Visual C++ 运行库合集 新版软件详情页 - 微软VC++运行库合集 我是运行一个java程序(内置jdk)报错如下,安装上述库后解决 Unable to load JVM ...
- 各个版本Microsoft Visual C++运行库下载地址
各个版本Microsoft Visual C++运行库下载 Microsoft Visual C++ 2005 Microsoft Visual C++ 2005 Redistributable Pa ...
- 静态库、动态库、静态链接、动态链接、系统运行库混合、MD MT默认库冲突问题
一.静态库项目 静态库lib:(注意和"静态运行库"区分) 就是.lib文件,一个.c或.cpp会编译成一个.obj,多个.obj可以组合成一个.lib库.lib=多个obj. ...
最新文章
- Windows安装用于OCR的Tesseract及使用命令行参数进行OCR
- 数据挖掘学习日志(part2)--主成分法确定权重与R实现
- SAP Spartacus的OccCmsPageNormalizer
- 使用postman测试接口
- wget 下载百度云jdk
- 安装完jdk在cmd输入Java没有反应的解决办法
- page cache和buffer cache之间的关系以及验证
- Cesium雷达放射波
- 开源项目——小Q聊天机器人V1.3
- 为什么说每个软件工程师,都该懂大数据技术?
- 没的选择时,存在就是合理的::与李旭科书法字QQ聊天记录
- 如何处理高并发和单点故障
- gnuplot(九)、gnuplot画矢量与颜色设置
- 移动电源最大多少毫安?移动电源多少毫安合适
- 忧桑三角形,调了半天,真忧桑TAT
- MongoDB内嵌文档查询
- 全栈式深度学习(概括实讲解)
- 题解:[USACO12MAR]花盆Flowerpot 【单调队列】
- 安卓导入自定义下载矢量图标
- 如何提交一份高质量的缺陷报告
热门文章
- seata:Error creating bean with name ‘globalTransactionScanner‘ defined in class path resource
- redis客户端 predis与phpredis 比较
- matlab zscore函数 数据的标准化处理
- 【新书推荐】崛起的超级智能:互联网大脑如何影响科技未来
- 微信小程序前端调用python后端的模型
- mac vbox 共享文件夹_Mac系统VirtualBox中CentOS 7.2启用共享文件夹
- Brave Game ——巴什博奕
- 如何制定软件项目测试计划
- Linux系统级IO②:RIO-带缓冲区IO实现
- 2021年MathorCup高校数学建模挑战赛——大数据竞赛A题