MD(d)、MT(d)编译选项

2023-12-05 22:48
文章标签 编译 选项 md mt

本文主要是介绍MD(d)、MT(d)编译选项,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、MD(d)、MT(d)编译选项的区别

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


本文内容转载自:http://www.cnblogs.com/cswuyg/archive/2012/02/03/2336424.html

这篇关于MD(d)、MT(d)编译选项的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/459434

相关文章

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.

C++/《C/C++程序编译流程》

程序的基本流程如图:   1.预处理        预处理相当于根据预处理指令组装新的C/C++程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。 读取C/C++源程序,对其中的伪指令(以#开头的指令)进行处理将所有的“#define”删除,并且展开所有的宏定义处理所有的条件编译指令,如:“#if”、“

编译linux内核出现 arm-eabi-gcc: error: : No such file or directory

external/e2fsprogs/lib/ext2fs/tdb.c:673:29: warning: comparison between : In function 'max2165_set_params': -。。。。。。。。。。。。。。。。。。 。。。。。。。。。。。。。 。。。。。。。。 host asm: libdvm <= dalvik/vm/mterp/out/Inte

OpenStack:Glance共享与上传、Nova操作选项解释、Cinder操作技巧

目录 Glance member task Nova lock shelve rescue Cinder manage local-attach transfer backup-export 总结 原作者:int32bit,参考内容 从2013年开始折腾OpenStack也有好几年的时间了。在使用过程中,我发现有很多很有用的操作,但是却很少被提及。这里我暂不直接

OpenStack实例操作选项解释:启动和停止instance实例

关于启动和停止OpenStack实例 如果你想要启动和停止OpenStack实例时,有四种方法可以考虑。 管理员可以暂停、挂起、搁置、停止OpenStack 的计算实例。但是这些方法之间有什么不同之处? 目录 关于启动和停止OpenStack实例1.暂停和取消暂停实例2.挂起和恢复实例3.搁置(废弃)实例和取消废弃实例4.停止(删除)实例 1.暂停和取消暂停实例

QT 编译报错:C3861: ‘tr‘ identifier not found

问题: QT 编译报错:C3861: ‘tr’ identifier not found 原因 使用tr的地方所在的类没有继承自 QObject 类 或者在不在某一类中, 解决方案 就直接用类名引用 :QObject::tr( )

【H2O2|全栈】Markdown | Md 笔记到底如何使用?【前端 · HTML前置知识】

Markdown的一些杂谈 目录 Markdown的一些杂谈 前言 准备工作 认识.Md文件 为什么使用Md? 怎么使用Md? ​编辑 怎么看别人给我的Md文件? Md文件命令 切换模式 粗体、倾斜、下划线、删除线和荧光标记 分级标题 水平线 引用 无序和有序列表 ​编辑 任务清单 插入链接和图片 内嵌代码和代码块 表格 公式 其他 源代码 预

hector_quadrotor编译总结 | ubuntu 16.04 ros-kinetic版本

hector_quadrotor编译总结 | ubuntu 16.04 ros-kinetic版本 基于Ubuntu 16.04 LTS系统所用ROS版本为 Kinetic hector_quadrotor ROS包主要用于四旋翼无人机的建模、控制和仿真。 1.安装依赖库 所需系统及依赖库 Ubuntu 16.04|ros-kinetic|Gazebo|gazebo_ros_pkgs|ge