首页
社区
课程
招聘
5
[原创]Runtime运行时库在MT与MD之间的差别
发表于: 2021-8-7 12:09 9040

[原创]Runtime运行时库在MT与MD之间的差别

2021-8-7 12:09
9040

各位也可在我的博客查看文章 -> 博客文章链接

VS Runtime(运行时)库的介绍

运行时库提供了很多变量(包括常量),还有很多类函数,比如字符串处理、输入与输出等。它们可以被静态编译到可执行文件(EXE或DLL),也可以被动态加载。

详细的说明可参考C runtime library (CRT) reference - Microsoft Docs。关于用到的库可参考C runtime (CRT) and C++ Standard Library (STL) .lib files

本文重点阐述运行时库在MT和MD之间的区别。

运行时库的区别

不管编译DLL还是EXE,都可以在VS中设置运行时库。

设置路径为工程属性->Configuration Properties->C/C++->Code Generation->Runtime Library

运行时库分4类:

  • MTd(Multi-threaded Debug)

  • MDd(Multi-threaded Debug DLL)

  • MT (Multi-threaded)

  • MD (Multi-threaded DLL)

其中最后带d的为Debug版本的运行时库,不带d的为Release版本的运行时库。MTd和MT的T代表静态库,MDd和MD的D代表动态库。

也就是说采用MTd或MT,运行时库会被编译进EXE或DLL里;而MDd或MD的情况下,在EXE启动或DLL被加载时,运行时库会作为DLL被动态载入。

因为DLL和EXE编译时采用MT(d)或MD(d)的结果是一样的,所以这里以EXE编译时采用MT或MD为例。

EXE编译时采用MT运行时库

  • EXE编译时依赖了其他库,这个库是静态库(x.lib)

    在EXE采取MT运行时库时,静态库(x.lib)的编译也必须是MT。因为静态库的原因,EXE只需要把自己需要的代码从静态库(x.lib)提取出来就行,不考虑静态库里的运行库。所以这种情况下EXE和静态库使用的运行时库是同一套代码,都是EXE的运行时库。

  • EXE编译时依赖了其他库,这个库是动态库(x.dll)

    在EXE采取MT运行时库时,动态库(x.dll)的编译也必须是MT。因为是动态库,EXE在加载动态库时,是将其全部代码(包括一份运行时库代码)加载进了EXE进程空间,这样EXE在运行时就包含了两套运行时库代码,一个是动态库的,一个是EXE的。

注:虽然EXE和DLL会用各自的运行时库,但它们用的都是进程默认堆(PEB->ProcessHeap),不存在EXE和DLL用的堆不一致的情况(网上有说使用的堆不一样,这种说法是错误的)。

EXE编译时采用MD运行时库

不管EXE依赖的其他库是静态库还是动态库,它们都必须采用MD来编译。这种情况下编译出来的EXE和DLL(或EXE和LIB)都依赖MD运行时库(即VCRUNTIMExx.dll、MSVCPxx.dll、ucrtbase.dll)。因为都依赖MD运行时库,所以EXE和DLL(或EXE和LIB)用的是同一套运行时库。

EXE依赖DLL,EXE和DLL都采用MT时可能会遇到的错误

根据上一节的描述,这种情况下,EXE和DLL会用各自的运行时库,这时会导致一种错误,如下代码所示:

1
2
3
4
5
6
7
// In EXE test.cpp
#include "dll.h"
int main(){
    std::string str = GetString();
    std::cout << str << "\n";
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// In DLL dll.h
#ifndef FUNC_TEST
#define FUNC_TEST extern "C" __declspec(dllimport)
#endif
FUNC_TEST std::string GetString();
 
 
// In DLL dll.cpp
#define FUNC_TEST extern "C" __declspec(dllexport)
#include "dll.h"
std::string GetString() {
    std::string str("hello world");
    return str;
}

以上代码会导致如下错误:

1
2
//assertion failed!
__acrt_first_block == header

这个问题的成因请看下一节。


[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

最后于 2021-8-7 13:58 被coneco编辑 ,原因:
收藏
免费 5
支持
分享
赞赏记录
参与人
雪币
留言
时间
Thead
为你点赞~
2024-4-10 12:12
PLEBFE
为你点赞~
2022-7-30 07:04
bxb
为你点赞~
2021-8-10 21:22
Foodie
为你点赞~
2021-8-9 10:27
默NJ
为你点赞~
2021-8-7 22:22
最新回复 (7)
雪    币: 2090
活跃值: (3948)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
对你的头像很有兴趣
2021-8-7 14:09
0
雪    币: 183
活跃值: (681)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
C++/WinRT
2021-8-7 20:26
0
雪    币: 3571
活跃值: (4328)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
总结:为了使程序能在其他电脑上运行,应该采用mtd或mt
2021-8-7 20:34
0
雪    币: 2689
活跃值: (4991)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学到了,感谢分享!
2021-8-7 22:22
0
雪    币: 5138
活跃值: (4925)
能力值: ( LV10,RANK:171 )
在线值:
发帖
回帖
粉丝
6
lhxdiao 对你的头像很有兴趣
出自“路人女主的女主之一”
2021-8-9 00:03
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
然而mfc扩展dll却似乎无法使用MT
2021-8-9 01:12
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册