Background
MSDN中对于在不同的配置下Link的LIB作了说明:
C Runtime Library:
| 开关 | 对应的库 | 版本 |
| /MD | MSVCRT.LIB | 多线程DLL的Release版本 |
| /MDd | MSVCRTD.LIB | 多线程DLL的Debug版本 |
| /MT | LIBCMT.LIB | 多线程静态链接的Release版本 |
| /MTd | LIBCMTD.LIB | 多线程静态链接的Debug版本 |
| /clr | MSVCMRT.LIB | 托管代码和非托管代码混合 |
| /clr:pure | MSVCURT.LIB | 纯托管代码 |
C++ Standard Library:
| 开关 | 对应的库 | 版本 |
| /MD | MSVCPRT.LIB | 多线程DLL的Release版本 |
| /MDd | MSVCPRTD.LIB | 多线程DLL的Debug版本 |
| /MT | LIBCPMT.LIB | 多线程静态链接的Release版本 |
| /MTd | LIBCPMTD.LIB | 多线程静态链接的Debug版本 |
编译器会自动根据编译选项,选择对应的LIB文件。一般情况下这不会出现问题。
然而,在部分情况下,一旦你的程序的各个部分(LIB, OBJ…)并非由相同的编译选项编译出,而Link在一起的话,会出现各种各样的看似很难解决的问题,这类问题主要以重复定义的错误形式存在,通常的解决方法也很简单,就是选择同样的编译选项进行编译之后再Link。
关于链接方式补充
1、为什么选择/MD,不选/MT?
(1)程序就不需要静态链接运行时库,可以减小软件的大小;
(2)所有的模块都采用/MD,使用的是同一个堆,不存在A堆申请,B堆释放的问题;
(3)用户机器可能缺少我们编译时使用的动态运行时库。(补充:如果我们软件有多个DLL,采用/MT体积增加太多,则可以考虑/MD + 自带系统运行时库)
选择/MD要注意“多个模块选择不同版本运行库”的问题:
1. 多个dll被一个exe LoadLibrary加载,如果这些dll使用的运行时库是不同的,那么可能出现加载失败,原因可能是旧版本的运行时库已经在了,而某个dll它需要的是新版本的运行时库,旧版本不符合要求。
2. 如果工程里所有的模块都是自己写的或者可以完全控制的,那么这个问题不难解决,只需要在工程设置里都设置/MD,然后在相同的环境下编译一次就行。但是假如这个模块是外界提供的呢?
3. 可能存在这种情况:A动态库使用了B静态库,B静态库使用了C动态库,B静态库是外界提供的,我们要使用它,但无法修改它,我们也无法接触到C动态库。如果C动态库使用的运行时库版本跟编译A动态库的本地使用的不一致,那么A动态库里的嵌入信息就会记录两个不同版本的运行时库,它被加载的时候,可能会选择版本新的。假设A动态库被一个exe LoadLibrary加载,而这个exe本身的运行时库是旧的,这样就会导致A动态库加载失败,即便把新的运行时库拷贝到目录下也不行,因为exe这个进程已经加载了那个旧的运行时库。这时候必须使用manifest文件指定嵌入到A动态库里的运行时库为某个版本,忽略掉C动态库使用的运行时库版本。
4. 这个问题挺复杂的,我心思没去验证windows的PE文件加载会对运行时库做什么样的优先选择、运行时库在静态库里的记录…。只要记住,给外界使用的组件版本尽量避免使用/MD(这样会导致膨胀吗?据说,安装包可以做字节流式压缩)。
5. 附上另一个问题:静态库的依赖关系: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抽筋了:)
2、为什么选择/MT,不选择/MD?
(1)有些系统可能没有程序所需要版本的运行时库,程序必须把运行时库静态链接上。
(2)减少模块对外界的依赖。
选择/MT 时存在一个“堆空间释放”的问题:
1. 不同的模块各自有一份C运行时库代码、或者根本没有C运行时库,导致了各个模块会有各自的堆。如果在A堆中申请空间,到B堆中释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。

本文详细介绍了C++编译时选择/MD和/MT链接运行时库的差异及其影响。/MD适用于减小程序大小和简化内存管理,但可能导致版本冲突;/MT则减少对外部依赖,但可能增加程序体积。文章讨论了多模块选择运行时库的一致性问题,以及如何解决动态库与静态库的运行时库版本不匹配问题。同时,提到了静态库的依赖处理和链接选项对程序行为的影响。
1787

被折叠的 条评论
为什么被折叠?



