问题
⼀、MD(d)、MT(d)编译选项的区别
1、编译选项的位置
以VS2005为例,这样⼦打开:
1) 打开项⽬的Property Pages对话框2) 点击左侧C/C++节3) 点击Code Generation节4) 右侧第六⾏Runtime Library项⽬
2、各个设置选项代表的含义
编译选项/MD
包含
_MT、_DLL
静态链接的libMSVCRT.lib说明多线程、Release、DLL版本的运⾏时库多线程、Debug、DLL版本的运⾏时库多线程、Release版本的运⾏时库多线程、Debug版本的运⾏时库/MDd
_DEBUG、_MT、MSVCRTD.lib_DLL_MT
_DEBUG、_MT
LIBCMT.libLIBCMTD.lib/MT/MTd
简单的说:
(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需要注意多个模块使⽤不同版本运⾏时库的问题
(2012-9-17补充) (2013.5.30补充)
多个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选项-->LinkLibrary 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附录:
因篇幅问题不能全部显示,请点此查看更多更全内容