转载 关于多线程MT和MD的区别。

这段时间司在招实习生,而不管是远程的电话面试或者是实际现场面试中领导都喜欢问你这个问题,但是可惜的是能很好答上来的人很少。后来发现不管是应届的实习生,甚至有些实际参加工作几年的人也未必真的了解这个问题。今天想写一篇详解,希望对广大程序员有一定的帮助。

区别1:全局堆句柄不一样。

网上有一个说法,就是一个线程一个栈,一个模块一个堆。前者很容易有理解,每个线程创建的时候在CreateThread中都能制定默认栈大小,只是很多情况下都取了默认值。而一个模块一个堆呢?其实很简单测试,如果是一个多线程MT编译方式的程序,你写一个dll,导出一个函数,参数设置为vector<int>,然后在exe中调用,当导出函数结束时就会崩溃掉。其实原因很简单,就是因为初始化向量空间时malloc内存的过程在exe中,而vector析构时会free内存,申请和释放的模块不一致而违背了一个模块一个堆的说法。

细心者会发现,其实不管是new/delete还是malloc/free最终调用的都是HeapAlloc/HeapFree,而这个函数的第一个参数为一个全局的堆句柄,由CreateHeap创建,创建该全局堆句柄的尚且在main等系列主函数之前。事实上这种夸模块堆操作异常总结起来就是申请内存时HeapAlloc传入的句柄和释放该内存时HeapFree传入的句柄不一致引起的,读者可写代码测试。

但是以上问题如果是多线程MD编译方式下便可解决,也就是说如果都是通过多线程MD编译方式出来的程序,如果是A模块中申请的内存到B模块中释放不会出现问题。

区别2:链接的运行时库不同。

对于多线程MT的程序来说,其连接的是libcmt.lib,该文件属于C语言运行时库,整个lib都会连接到PE文件当中。而多线程MD的程序链接的却是类似msvcpXXX.dll,该文件属于微软运行时库.也就是说如果是多线程MD编译出来的文件运行时都会加载相应版本的运行时库,当如果找不到运行时库就会报错而无法运行,同时如果运行时库不匹配也会出现各种意料之外的崩溃或者程序根本跑不起来等情况。

区别3:编译出来的PE文件大小区别

此时如果两者作为对比就会很明显看到多线程MT编译出来的文件体积要比多线程MD编译出来的大,因为MT是把对应的运行时库直接放到编译出来的PE文件当中,而MD却是运行的时候从第三方dll中获取运行时库,自己本身却不包含。同时另外的区别也很明显,多线程MT编译出来的文件运行时不需要加载第三方dll所以运行效率要比多线程MD稍微高一点点,当然作为用户是完全感觉不到的。所以说如果打开一个程序目录,发现里面有类似msvcrtXX.dll,那么这个程序几乎可以肯定是用多线程MD方式编译的。

以上区别一言以蔽之就是多线程MT加载的是静态运行时库,属于C语言版本;而多线程MD版本加载是动态运行时库,属于微软版本。

总结:其实绝大多数软件都是采用多线程MD方式编译,例如QQ迅雷等等,如果找到他们目录很容易发现上面提到的运行时库。因为这样一来编译出来的文件小,所有运行时库统一,同时也让内存管理简单化,省去了跨模块内存访问带来的各种bug。

时间: 2024-09-26 16:02:53

转载 关于多线程MT和MD的区别。的相关文章

基于Java多线程notify与notifyall的区别分析_java

当一个线程进入wait之后,就必须等其他线程notify/notifyall,使用notifyall,可以唤醒所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个.注意,任何时候只有一个线程可以获得锁,也就是说只有一个线程可以运行synchronized 中的代码,notifyall只是让处于wait的线程重新拥有锁的争夺权,但是只会有一个获得锁并执行. 那么notify和notifyall在效果上又什么实质区别呢?主要的效果区别是notify用得不好容易导致死锁,

[转载]GIF、JPEG 和 PNG的区别在哪里?

原文地址:GIF.JPEG 和 PNG的区别在哪里?作者:苗得雨 GIF.JPEG 和 PNG 是三种最常见的图片格式. GIF:1987 年诞生,常用于网页动画,使用无损压缩,支持 256 种颜色(一般叫 8 bit 彩色),支持单一透明色: JPEG:1992 年出世,照片一般都用这个格式,有损压缩,24 bit 真彩色(224 = 17 万种颜色),不支持动画,不支持透明色: PNG:1996 年问世,无损压缩,最常见的使用格式是 256 索引色(PNG-8)和 24 bit 真彩色(PN

多线程Runnable和Thread产生线程

  http://dev.yesky.com/186/2547686.shtml public class Test { public static void main(String[] args) throws Exception{ MyThread mt = new MyThread(); mt.start(); mt.join(); Thread.sleep(3000); mt.start(); } } 当线程对象mt运行完成后,我们让主线程休息一下,然后我们再次在这个线程对象上启动线程.

android java-多线程Thread与Runable的区别

问题描述 多线程Thread与Runable的区别 多线程Thread与Runable的区别,优缺点.请大神们指教一下啊 解决方案 两者完全没有可比性.Runable为线程提供了一个可以执行的函数.Java语言没有函数指针,所以为了传一个函数给jvm,只能传一个接口,并且把实现的方法写在这个接口的实现类中. 解决方案二: Thread是类,runable是接口.1.使用接口可以多处使用,减少代码重复.2.使用runable看着高大上一点 解决方案三: 项目中用Runnable用的多.

boost全平台编译方法

1.通用规则 多数库是不需要预先编译的,include hpp文件就能用.如果出现链接失败,那就是可能需要编译库了. boost自带一套编译工具bjam,bjam本身是跨平台的,并且也要自行编译出来.在boost目录下有bootstrap.sh和bootstrap.bat两个脚本分别用来编译*nix和windows下的bjam.bootstrap脚本可以传入参数,以在编译bjam过程中生成特定的编译boost的配置.这些配置保存在新生成的project-config.jam里,但还可以在运行bj

独家电影营销分析:《决战刹马镇》的得与失

<决战刹马镇>是一部癫狂电影,癫狂的不仅是剧情和表演方式,观众反应也同样癫狂.喜欢的大赞其能让人狂笑90分钟,厌恶的批其莫名奇妙,不知所云.据笔者观察,对待本片的态度跟观众的文化水平.道德修养.观影多少似乎并无直接关系.这是一部值得制片单位仔细研究的作品. 本文主要从以下几个方面为您梳理本片的得与失: 1.作为一部新类型喜剧电影,片方似乎过分自信,成本控制意识不强造成收回投资的压力较大: 2.档期竞争激烈造成排片不足: 3.宣传规模足够,但宣传点单一,无法吸引更大的公众的关注度: 4.世界杯对

vs2010发布时去除msvcp100.dll和msvcr100.dll图解说明

最近开发个程序,Copy到虚拟机环境中测试时提示缺少msvcr100.dll,于是想到编译时设置选项去除依赖. 什么是 msvcr100.dll MS = MicrosoftV = VisualC = C program languageR = Run-time100 = Version 什么是 msvcp100.dll MS = MicrosoftV = VisualCP = C++100 = version 解决的办法 Release版本 Visual Studio 2010, 打开菜单中的

在网上搜到的题目

CC++ 题集(CC++试题和部分答案)1. 以下三条输出语句分别输出什么?[C易] char str1[]       = "abc"; char str2[]       = "abc"; const char str3[] = "abc";  const char str4[] = "abc";  const char* str5   = "abc"; const char* str6   = &qu

windowsxp系统无法运行vs生成的程序怎么办

windowsxp系统无法运行vs生成的程序怎么办   具体如下: 1.项目->属性; 2.常规->平台工具集,选择"VS2013WindowsXP(v120_xp)"; 3.再次运行还会出错,情况如下,不要着急接着看; 4.C/C++->代码生成->运行库,选择"多线程(/MT)"; 5.如果还不能运行请设置如下属性: 1.项目菜单->项目属性->链接器->系统->子系统->控制台或窗口windows(根据你的