关于多线程md mtT和MD的区别

2011年11月 专题开发/技术/项目大版内专家分月排行榜第一2011年10月 专题开发/技术/项目大版内专家分月排行榜第一2011年9月 专题开发/技术/项目大版内专家分月排行榜第一2011年8月 专题开发/技术/项目大版内专家分月排行榜第一2011年7月 专题开发/技术/项目大版内专家分月排行榜第一2011年6月 C/C++大版内专家分月排行榜第一
2011年7月 C/C++大版内专家分月排行榜第二2011年5月 专题开发/技术/项目大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。MD(d)、MT(d)编译选项的区别
1、编译选项的位置
以VS2005为例,这样子打开:
1)&&&&&&&&&打开项目的Property&Pages对话框
2)&&&&&&&&&点击左侧C/C++节
3)&&&&&&&&&点击Code&Generation节
4)&&&&&&&&&右侧第六行Runtime&Library项目
2、各个设置选项代表的含义
静态链接的lib
MSVCRT.lib
多线程、Release、DLL版本的运行时库
_DEBUG、_MT、_DLL
MSVCRTD.lib
多线程、Debug、DLL版本的运行时库
LIBCMT.lib
多线程、Release版本的运行时库
_DEBUG、_MT
LIBCMTD.lib
多线程、Debug版本的运行时库
简单的说:
(1)/MD,表示运行时库由操作系统提供一个DLL,程序里不集成。
(2)/MT,表示运行时库由程序集成。
二、/MD、/MT的选择
&&&&&&1、为什么选择/MD,不选/MT?
&&&&&&&&&(1)程序就不需要静态链接运行时库,可以减小软件的大小;
&&&&&&&&&(2)所有的模块都采用/MD,使用的是同一个堆,不存在A堆申请,B堆释放的问题;
  &(3)用户机器可能缺少我们编译时使用的动态运行时库。(补充:如果我们软件有多个DLL,采用/MT体积增加太多,则可以考虑/MD&+&自带系统运行时库)
&&&&&&2、为什么选择/MT,不选择/MD?
&&&&&&&&&(1)有些系统可能没有程序所需要版本的运行时库,程序必须把运行时库静态链接上。
  &&&(2)减少模块对外界的依赖。
&&&&&&3、多个模块,必须选择相同的运行时库。
三、选择/MT需要解决的堆空间释放问题
&&&&&&&&&不同的模块各自有一份C运行时库代码、或者根本没有C运行时库,导致了各个模块会有各自的堆。如果在A堆中申请空间,到B堆中释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。
&&&&&&&&&附录的DLL以及DLLUser代码,以STL的string为例,通过修改编译选项验证了这个问题。string在赋值的时候需要释放掉原来的内存空间,然后再申请新的内存空间存储新的内容,如果跨模块了,释放的时候就存在“A模块申请B模块释放”的问题,导致程序崩溃。
&  (跨模块释放内存导致崩溃的内容,在《windows核心编程》第五版Page511谈DLL和进程的地址空间时有谈到)
四、选择/MD需要注意多个模块使用不同版本运行时库的问题
&&&&&多个dll被一个exe&LoadLibrary加载,如果这些dll使用的运行时库是不同的,那么可能出现加载失败,原因可能是旧版本的运行时库已经在了,而某个dll它需要的是新版本的运行时库,旧版本不符合要求。
&&&&&如果工程里所有的模块都是自己写的或者可以完全控制的,那么这个问题不难解决,只需要在工程设置里都设置/MD,然后在相同的环境下编译一次就行。但是假如这个模块是外界提供的呢?
&&&&&可能存在这种情况:A动态库使用了B静态库,B静态库使用了C动态库,B静态库是外界提供的,我们要使用它,但无法修改它,我们也无法接触到C动态库。如果C动态库使用的运行时库版本跟编译A动态库的本地使用的不一致,那么A动态库里的嵌入信息就会记录两个不同版本的运行时库,它被加载的时候,可能会选择版本新的。假设A动态库被一个exe&LoadLibrary加载,而这个exe本身的运行时库是旧的,这样就会导致A动态库加载失败,即便把新的运行时库拷贝到目录下也不行,因为exe这个进程已经加载了那个旧的运行时库。这时候必须使用manifest文件指定嵌入到A动态库里的运行时库为某个版本,忽略掉C动态库使用的运行时库版本。
&&&&&这个问题挺复杂的,我心思没去验证windows的PE文件加载会对运行时库做什么样的优先选择、运行时库在静态库里的记录…。只要记住,给外界使用的组件版本尽量避免使用/MD(这样会导致膨胀吗?据说,安装包可以做字节流式压缩)。
  附上另一个问题:静态库的依赖关系:exe--&libA--&libB,现在不想让exe接触到libB,于是把libA的librarian选项--&General选项--&Link&Library&Dependencies设置为Yes,这样即可,libA会包含libB,exe只需要接触libA。另外需要特别注意,libA对libB的依赖只需要且只能在Solution的Project&Dependencies里设置,如果在libA的代码里写了”#pragma&comment(lib,&&libB.lib&)”,会导致exe在link&libA的时候提示找不到libA。如果exe还出现link错误,那一定是VS抽筋了:)
五、参考资料
1、微软关于MT、MD等的详细介绍
2、不要出现A模块申请,B模块释放的情况
3、运行时库有哪些版本
4、CSDN上关于堆空间释放的讨论
5、不同模块不同的堆
6、因为运行时库版本问题导致加载失败的分享
7、《windows核心编程》
8、windows&heap跟CRT&heap
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:5485次
排名:千里之外
原创:12篇
转载:30篇
(1)(2)(2)(1)(3)(5)(5)(5)(3)(3)(3)(6)(4)下次自动登录
现在的位置:
& 综合 & 正文
/MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
一、MD(d)、MT(d)编译选项的区别
1、编译选项的位置
以VS2005为例,这样子打开:
打开项目的Property Pages对话框
点击左侧C/C++节
点击Code Generation节
右侧第六行Runtime Library项目
2、各个设置选项代表的含义
静态链接的lib
MSVCRT.lib
多线程、Release、DLL版本的运行时库
_DEBUG、_MT、_DLL
MSVCRTD.lib
多线程、Debug、DLL版本的运行时库
LIBCMT.lib
多线程、Release版本的运行时库
_DEBUG、_MT
LIBCMTD.lib
多线程、Debug版本的运行时库
简单的说:
(1)/MD,表示运行时库由操作系统提供一个DLL,里不集成。
(2)/MT,表示运行时库由程序集成。
二、/MD、/MT的选择
1、为什么选择/MD,不选/MT?
(1)程序就不需要静态链接运行时库,可以减小软件的大小;
(2)所有的模块都采用/MD,使用的是同一个堆,不存在A堆申请,B堆释放的问题。
2、为什么选择/MT,不选择/MD?
(1)有些系统可能没有程序所需要版本的运行时库,程序必须把运行时库静态链接上。
3、多个模块,必须选择相同的运行时库。
三、选择/MT需要解决的堆空间释放问题
不同的模块各自有一份C运行时库、或者根本没有C运行时库,导致了各个模块会有各自的堆。如果在A堆中申请空间,到B堆中释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。
附件(下载地址:/cswuyg/Test_MD_and_MT.rar)的DLL以及DLLUser代码,以STL的string为例,通过修改编译选项验证了这个问题。(string在赋值的时候需要释放掉原来的空间,然后再申请新的空间存储新的内容。)
四、参考资料
1、微软关于MT、MD等的详细介绍
2、不要出现A模块申请,B模块释放的情况
3、运行时库有哪些版本
4、CSDN上关于堆空间释放的讨论
5、不同模块不同的堆
测试代码下载地址
/cswuyg/Test_MD_and_MT.rar
&&&&推荐文章:
【上篇】【下篇】程序运行时出现问题,选择的是Release,win64位的模式,并且已经看到了宏定义NDEBUG,但是程序依然进入上面的部分
解决方案是将属性-&C/C++-&代码生成器-&运行库里面的多线程调试(/MTD)修改为多线程DLL(/MD)即可
修改之后:
解释原因来自&http://blog.csdn.net/u/article/details/,感谢~~
这里总结下他们的区别,后面的那个'd'是代表DEBUG版本,没有'd'的就是RELEASE版本了。
/MT是 "multithread, static version & 意思是多线程静态的版本,定义了它后,编译器把LIBCMT.lib 安置到OBJ文件中,让链接器使用LIBCMT.lib 处理外部符号。
/MD是 "multithread- and DLL-specific version& ,意思是多线程DLL版本,定义了它后,编译器把 MSVCRT.lib 安置到OBJ文件中,它连接到DLL的方式是静态链接,实际上工作的库是MSVCR80.DLL。
静态运行时库:LIBCMT.lib动态运行时库:MSVCRT.lib + MSVCR80.DLL
所以,当你用CMAKE生成工程文件时,若CMAKE是用/MT生成的(查看工程原始目录的CMakeLists.txt),则它所调用的运行时库为:LIBCMT.lib,若生成的工程的运行时库(Runtime Library)你选择/MD,则此工程在编译后链接的时候,将会调用动态运行时库:MSVCRT.lib + MSVCR80.DLL,明显,两次对同一个某运行时库里的函数调用的库不同,则会出现重定义的错误。若此工程生成的是库文件,则其他工程调用此库时也必须是/MT。
===============================================
&配置属性&C/C++&代码生成&运行时库 可以采用的方式有:多线程(/MT)、多线程调试(/MTd)、多线程DLL(/MD)、多线程调试DLL(/MDd)、单线程(/ML)、单线程调试(/MLd)。
Reusable Library Switch Library Macro(s) Defined
Single Threaded
Static MultiThread
Dynamic Link (DLL)
_MT and _DLL
Debug Single Threaded
Debug Static MultiThread
_DEBUG and _MT
Debug Dynamic Link (DLL)
_DEBUG, _MT, and _DLL
& &其中以小写&d&结尾的选项表示的DEBUG版本的,没有&d&的为RELEASE版本。大型项目中必须要求所有组件和第三方库的运行时库是统一的,否则将会出现井喷。
&&& 单线程运行时库选项/ML和/MLd在VS2003以后就被废了。
&&& /MT和/MTd表示采用多线程CRT库的静态lib版本。该选项会在编译时将运行时库以静态lib的形式完全嵌入。该选项生成的可执行文件运行时不需要运行时库dll的参加,会获得轻微的性能提升,但最终生成的二进制代码因链入庞大的运行时库实现而变得非常臃肿。当某项目以静态链接库的形式嵌入到多个项目,则可能造成运行时库的内存管理有多份,最终将导致致命的&Invalid Address specified to RtlValidateHeap&问题。另外托管C++和中不再支持/MT和/MTd选项。
&&& /MD和/MDd表示采用多线程CRT库的动态dll版本,会使应用程序使用运行时库特定版本的多线程DLL。链接时将按照传统VC链接dll的方式将运行时库MSVCRxx.DLL的导入库MSVCRT.lib链接,在运行时要求安装了相应版本的VC运行时库可再发行组件包(当然把这些运行时库dll放在应用程序目录下也是可以的)。&因/MD和/MDd方式不会将运行时库链接到可执行文件内部,可有效减少可执行文件尺寸。当多项目以MD方式运作时,其内部会采用同一个堆,内存管理将被简化,问题也能得到缓解。
&&& 结论:/MD和/MDd将是潮流所趋,/ML和/MLd方式请及时放弃,/MT和/MTd在非必要时最好也不要采用了。
阅读(...) 评论()}

我要回帖

更多关于 多线程md mt 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信