65.9K
CodeProject 正在变化。 阅读更多。
Home

关于 VC++ CRT 的短篇故事

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.15/5 (22投票s)

2007年8月28日

CPOL

3分钟阅读

viewsIcon

62574

各种 CRT (ML, MT, MD) 的特性以及解决初学者经常遇到的问题的方法

什么是 CRT?

CRT 是 C 运行时库的缩写。它是一个包含所有 C 标准函数的庞大库。您最初学习 C 语言时使用的所有函数,例如 printfscanffgets 等,都包含在这个库中。基本上,Visual C++ 有三种 CRT。它们分别是单线程 (ML)、多线程 (MT) 和多线程 DLL (MD)。这些 CRT 中的每一个都有两个版本,分别是调试版和发布版,因此在 VC++ 中严格来说有六个 CRT 库。

CRT 特性

它们制作多达六个包含相同函数的库的原因,类似于 Baskin Robbins 有超过 30 种冰淇淋。它的理念是选择最适合您条件的库。就像所有冰淇淋都有不同的味道一样,这些库也有细微的差异。表 1 显示了每个 CRT 的特性。调试 CRT 有一些额外的功能,例如断言警报、内存泄漏检测等。

表 1:CRT 特性

CRT Characteristics
单线程 libc.lib
libcd.lib
它仅为单线程程序制作,并且比多线程 CRT 稍快。此 CRT 中包含的某些函数在多线程版本中无法正常运行。自 Visual Studio 2005 以来,Microsoft 就不再支持这种类型的 CRT。
多线程 libcmt.lib
libcmtd.lib
此 CRT 中的所有函数在多线程环境中都是安全的。
多线程 DLL msvcrt.lib
msvcrtd.lib
与多线程 CRT 相同,但 CRT 函数位于单独的 DLL 中。因此,有许多模块使用此 CRT,并且程序的总大小减小了。此 CRT 的缺点是需要将程序与 CRT DLL 一起分发。

如何选择 CRT

如果您的程序没有库,您只需根据其特性选择 CRT 即可。更改 CRT 的方法很简单。首先,打开项目属性对话框,然后选择 C/C++ 选项卡中的代码生成(参见图 1)。现在您可以看到“运行时库”字段。将该字段更改为您的 CRT,然后重新构建您的项目。就这些了。

图 1:项目属性对话框中的运行时库
Screenshot - crt1.png

但是,如果存在静态库或动态链接库,则选择就没那么简单了。首先,您必须知道这些库的绑定时间。静态库在编译时绑定,但动态链接库在运行时绑定。它们最终都在您程序的同一内存空间中执行。

链接静态库最常见的问题是 CRT 冲突,当程序链接的 CRT 与库使用的 CRT 不同时。由于每个 CRT 都有相同的函数,因此它们不能同时链接。此问题有两种解决方案。一种是使用程序使用的相同 CRT 重新编译所有库。另一种是在项目属性对话框中添加一个 CRT 来忽略库字段(参见图 2)。

图 2:项目属性对话框中忽略特定库
Screenshot - crt2.png

动态链接库的主要问题是 new/delete 问题。如果您的程序和 DLL 链接了多线程或单线程 CRT,则您的程序和 DLL 将使用不同的堆。因此,释放 DLL 的内存,在程序中分配内存或反之,会造成运行时错误(参见列表 1 和列表 2)。您应该使用多线程 DLL CRT 或不要在 DLL 边界之外使用 new/delete 来解决此问题。

列表 1:在 DLL 边界之外使用 New/delete 的错误代码

//CreateCar is a dll function.  

Car *car = CreateCar();  
delete car; 

列表 2:修复的未使用 DLL 边界之外 New/delete 的代码

//CreateCar, DestroyCar is a dll function  

Car *car = CreateCar();  
DestroyCar(car); 

结论

为了避免复杂的问题,更好的方法是使用相同的 CRT,并编写一个不在 DLL 边界之外使用 new/delete 的程序。

历史

  • 2007 年 8 月 28 日 - 发布原始版本
© . All rights reserved.