MT还是MD

说来也奇怪,为什么MSVC里面会出现MT和MD这两种模式?之前对此几乎是一无所知,但是最近遇到的关于这个选项的问题越来越多,所以特意花点时间研究一下这两种模式在使用时候的一些特征。作为对比,分别用一个静态库和一个调用这个静态库的exe文件来作为测试条件,分别用/MT和/MD两种选项编译,所以最后有四个测试程序:mt_mt,mt_md和md_md,md_mt:

首先是我们的静态库,为了简单和便利,加了一个头文件,实现里只保留一个函数,总之越小越好:

然后是lib.c

这么写还有一个目的,测试一下宏定义中字符的联接功能。最后是主程序,在里面调用静态库里的接口:

上面的这些都不是重点,此处的主要目的是看一下MT和MD程序在链接在一起的时候所表现出来的特征,首先将静态库分别用/MT和/MD两个选项各build出来一个版本,对应lib_mt.lib和lib_md.lib,以如下方式编译链接:

接下来用/MT和/MD选项分别编译出来对应版本的libcall的obj文件-libcall_mt.obj和libcall_md.obj文件,然后用这两个文件分别去链接lib_mt.lib和lib_md.lib,看看链接器会不会提示错误:

mt1

上面的错误很明显,用MT的obj链接MD的静态库,无法正常链接通过,这里没有用/nologo是为了对比不用版本下vs提供的工具具有的不同特征

md1

用MD的obj去链接MT的静态库,在vs2015版本下则没有出现任何错误,虽然两个文件/MT和/MD选项不一致的时候,都会提示一个4098的警告,但是链接器还是妥协并生成了exe文件。下面就以MT的obj链接MD的.lib库继续测试,在这之前,先看一下/MT和/MD编译方法默认的defaultlib分别是什么,通过notpad++打开mt和md的obj或者.lib文件,然后搜索defaultlib就可以看到系统默认的库文件,/MT对应的是libcmt.lib,/MD对应的是msvcrt.lib,所以接下来使用/nodefaultlib:msvcrt.lib忽略掉这个默认库然后再链接生成libcall_mt_with_md.exe:

mt2

错误少了一个,但是还有一个无法解析的符号错误,难道是因为这里以.lib为取决因素?那就忽略掉libcmt.lib再看一下效果

mt3

成功了,没有输出任何的错误,看来vs2015中/MD优先于/MT,假设要把各种版本的obj或者lib文件链接到一块,VS2015都会强制建议你最终生成"/MD"的模式,而且它不会主动忽略conflict的库,通过CFF Explorer查看四个exe程序中的import directory,就可以看到情况确实是这样,只有mt_with_mt的程序中,不包含vc runtime库,其他成功编译链接出来的程序,都会包含runtime库。最后在vs2013和vs2010上,各做了一个测试,发现不使用/nodefaultlib:libcmt.lib都可以正常通过,如下

mt_with_md4_vs2013

mt_with_md5_vs2010

说明vs新版本中对/MT和/MD选项的处理机制确实是发生了变化的。在vc6时期,还有一个/ML选项,目测在vs2010以上的版本中都已取消,毕竟单线程已经没有什么实用性了,下面是MSDN官方给出的冲突列表:

To use this run-time library Ignore these libraries
Single-threaded (libc.lib) libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Multithreaded (libcmt.lib) libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Multithreaded using DLL (msvcrt.lib) libc.lib, libcmt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Debug Single-threaded (libcd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcmtd.lib, msvcrtd.lib
Debug Multithreaded (libcmtd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, msvcrtd.lib
Debug Multithreaded using DLL (msvcrtd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib

For example, if you received this warning and you want to create an executable file that uses the non-debug, single-threaded version of the run-time libraries, you could use the following options with the linker:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据