1、编译选项的位置

以VS2005为例,这样子打开:

1)         打开项目的Property Pages对话框

2)         点击左侧C/C++节

3)         点击Code Generation节

4)         右侧第六行Runtime Library项目

2、各个设置选项代表的含义

编译选项

包含

静态链接的lib

说明

/MD

_MT、_DLL

MSVCRT.lib

多线程、Release、DLL版本的运行时库

/MDd

_DEBUG、_MT、_DLL

MSVCRTD.lib

多线程、Debug、DLL版本的运行时库

/MT

_MT

LIBCMT.lib

多线程、Release版本的运行时库

/MTd

_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需要注意多个模块使用不同版本运行时库的问题

(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选项-->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等的详细介绍

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

2、不要出现A模块申请,B模块释放的情况

http://www.cnblogs.com/minggoddess/archive/2010/12/15/1907179.html

3、运行时库有哪些版本

http://www.cppblog.com/MichaelLiu/articles/10607.html

4、CSDN上关于堆空间释放的讨论

http://topic.csdn.net/t/20010112/09/57983.html

http://topic.csdn.net/t/20031009/17/2338051.html

http://topic.csdn.net/u/20090502/00/bf1602e3-ddf5-49b0-af81-8a23383f9ddc.html

http://blog.csdn.net/blz_wowar/article/details/2176536

5、不同模块不同的堆

http://www.cnblogs.com/WengYB/archive/2011/08/18/2144727.html

6、因为运行时库版本问题导致加载失败的分享

http://blog.csdn.net/dev_yarin/article/details/6768373

http://blog.163.com/henan_lujun/blog/static/19538333200611485511640/

7、《windows核心编程》

8、windows heap跟CRT heap

http://social.msdn.microsoft.com/Forums/vstudio/en-US/1e67edb1-9c2f-4f30-985a-7a0969366b1a/windows-heap-vs-crt-heap?forum=vcgeneral

http://msdn.microsoft.com/en-us/library/ms810466.aspx

MD(d)、MT(d)编译选项的区别的更多相关文章

  1. 编程 MD(d)、MT(d)编译选项的区别

    转:http://blog.csdn.net/nodeathphoenix/article/details/7550546 1.各个选项代表的含义 编译选项 包含 静态链接的lib 说明 /MD _M ...

  2. /MD、/MT、/LD( 使用 多线程版本 运行时库的C runtime library)

    /MD./MT./LD(使用运行时库)(微软官网解释) Visual C++ 编译器选项 /MD./ML./MT./LD 区别 指定与你项目连接的运行期库 /MT多线程应用程序 /Mtd多线程应用程序 ...

  3. 1.改变项目 动态库、静态库属性。 2.使用运行库 /MD、/MT、/LD说明

    /MD./MT./LD(使用运行库) 有关 C 运行库以及使用 /clr(公共语言运行时编译) 进行编译时要使用哪些库的更多信息,请参见 CRT 库功能. 传递给链接器的给定调用的所有模块都必须使用相 ...

  4. VC运行时库(/MD、/MT等)

    VC项目属性→配置属性→C/C++→代码生成→运行时库 可以采用的方式有:多线程(/MT).多线程调试(/MTd).多线程DLL(/MD).多线程调试DLL(/MDd).单线程(/ML).单线程调试( ...

  5. /MT /MD /ML /MTd /MDd /MLd 的区别

    Multithreaded Libraries Performance The single-threaded CRT is no longer ( in vs2005 ) available. Th ...

  6. /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题

    一.MD(d).MT(d)编译选项的区别 1.编译选项的位置 以VS2005为例,这样子打开: 1)         打开项目的Property Pages对话框 2)         点击左侧C/C ...

  7. C/C++ Learning

    目录 1. C/C++中的关键字2. C/C++中的标识符3. 编译选项MD(d).MT(d)编译选项的区别4. C++类模板.函数模板5. C++修饰符6. 调用约定7. 错误处理8. 环境表 9. ...

  8. VC编译那些事儿

    转载自:http://blog.csdn.net/wowolook/article/details/8077153     最近又被ms的编译选译纠结了一下,运行程序是老是弹出0x14b1 or 71 ...

  9. 多线程MT和多线程MD的区别

    这段时间司在招实习生,而不管是远程的电话面试或者是实际现场面试中领导都喜欢问你这个问题,但是可惜的是能很好答上来的人很少.后来发现不管是应届的实习生,甚至有些实际参加工作几年的人也未必真的了解这个问题 ...

随机推荐

  1. Linq之Lambda进阶

    目录 写在前面 系列文章 带有标准查询运算符的Lambda Lambda中类型推断 Lambda表达式中变量作用域 异步Lambda 总结 写在前面 上篇文章介绍了Lambda的基本概念以及匿名方法, ...

  2. EntityFramework_MVC4中EF5 新手入门教程之七 ---7.通过 Entity Framework 处理并发

    在以前的两个教程你对关联数据进行了操作.本教程展示如何处理并发性.您将创建工作与各Department实体的 web 页和页,编辑和删除Department实体将处理并发错误.下面的插图显示索引和删除 ...

  3. 第一章:javascript: 数据结构与算法

    在前端工程师中,常常有一种声音,我们为什么要学数据结构与算法,没有数据结构与算法,我们一样很好的完成工作.实际上,算法是一个宽泛的概念,我们写的任何程序都可以称为算法,甚至往冰箱里放大象,也要通过开门 ...

  4. navigationBar设置透明度

    将NavigationBar设置透明(仅将指定视图控制器进行透明处理),步骤如下:1.在视图控制器的头文件中实现UINavigationControllerDelegate,例如:@interface ...

  5. Daily Scrum – 1/7

    Meeting Minutes 搞定了一个bug,单词面板滚动条的bug: 在电脑屏幕上的屏幕适配有了新思路: Progress   part 组员 今日工作 Time (h) 明日计划 Time ( ...

  6. u1-nav-html

    <header id="masthead" class="masthead" role="banner"> <nav cl ...

  7. 利用css3实现超出文本指定行数与省略号效果

    <style> .text1 {/*单行*/ width:200px; overflow:hidden; text-overflow:ellipsis; -o-text-overflow: ...

  8. Vijos p1892 树上的最大匹配 树形DP+计数 被卡常我有特殊技巧heheda

    https://vijos.org/p/1892 此题需要手动开栈: <<; //256MB char *p=(char*)malloc(size)+size; __asm__(" ...

  9. 如何解决mysql数据库X小时无连接自动关闭

    windows下打开my.ini,增加: interactive_timeout=28800000 wait_timeout=28800000 专家解答:MySQL是一个小型关系型数据库管理系统,由于 ...

  10. dict内部方法

    代码: #dict内部方法 vdic={'name':'kamil','age':23} print(dir(vdic)) vdic1 = vdic.copy()#copy(self):浅拷贝 pri ...