VS平台下MT与MD的区别

简单一点理解就是多线程/MT是将程序依赖的部分系统库静态链接进你的dll或者exe,而多线程DLL /MD则是依赖于dll(例如:vcruntime140.dll,msvcp140.dll),所以经常可以看到MD程序发布时需要拷贝一大堆的系统库。具体介绍参考下面两份文章:

VS项目属性中C/C++运行库 、MT /MTd /MD /MDd_ymxwz的专栏-CSDN博客

C Runtime Library 的来历_nodeathphoenix的专栏-CSDN博客

VS平台下MT与MD的区别

 对于MT于MD的了解源于我们的dll库需要给别人调用,但我们的dll又依赖log4cpp-1.1.3,因此有两种选择:

1、将自己的dll,log4cpp.dll,以及log4cpp依赖的所有系统库统一打包拷贝。

        那么调用者也可能会依赖相同的系统库,那么可能由于版本不同会导致冲突

2、将我们所依赖的所有开源库编译为MT。

首先编译MD版的log4cpp会报两个错误,向预处理器定义中添加HAVE_SNPRINTF即可成功编译。

将MD改为MT后编译,则会出现许多已导入本地符号的警告和无法解析的外部符号错误:
例如:错误    LNK2001    无法解析的外部符号 __imp___unlink    log4cpp   
警告    LNK4049    已导入本地定义的符号 ___std_exception_destroy    log4cpp   

看上去像是依赖库加载的不对,首先忽略特定库OLDNAMES.lib,由于系统库是默认加载,猜测可能是编译器加载问题。

首先通过Dependency Walker导入编译好的MD版log4cpp.dll,查看依赖的系统库:

VS平台下MT与MD的区别

 全局搜索了一下,只要MSVCP140.lib和VCRUNTIME140.lib没有。搜索一番后,发现VCRUNTIME140的静态库名叫libvcruntime.lib,参考:

vc编译去掉vcruntime140.dll依赖_weixin_33785108的博客-CSDN博客

而其余系统库可以通过下面链接搜索到对应lib库:

C 运行时 (CRT) 和 C++ 标准库 .lib 文件 | Microsoft Docs

于是准备手动向链接器-输入-附加依赖项添加libucrt.lib libcmt.lib libvcruntime.lib libcpmt.lib,编译后发现错误:
错误    LNK2038    检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”(AbortAppender.obj 中)    log4cpp 

看来手动加载所需lib库是失败了。

毫无头绪时看到预处理器定义中有这么几个包含敏感词dll的宏,预感应该是有点问题

VS平台下MT与MD的区别

将以上四个删除后居然编译通过!

LOG4CPP开头的两个宏是用于dllexport dllimport的,删除后会删除log4cpp的符号,无法外部调用它的接口。需要加上

_USRDLL是表示做一个用户DLL,默认加上

那么问题就出在_DLL,搜索后得知_DLL是用于表示MD的。参考:

VC预定义宏 - qinfengxiaoyue - 博客园

那么问题就解决了,不清楚是否是log4cpp最新是使用vs2010,该编译器可能不支持ui设置MD、MT,需要手动设置宏。

上一篇:Android smack 工具类(包含连接及相关方法)


下一篇:Out-of-distribution Detection系列专栏(二)