[转帖]你所不知道的C和C++运行库
[C-C++]你所不知道的C和C++运行库
https://blog.csdn.net/humanking7/article/details/85887884 原作者也是转的blog 最近一个物理机上面的workstation 总是缺少一个dll 启动不起来 折腾了很久 突然想起来 我这边机器还经常缺少MSVCR100 之类的dll 今天晚上心血来潮 趁着孩子睡觉 翻一下blog 解决了之前一直迷惑的地方。 不同版本 不同依赖关系 需要的vc++ runtime 是不一样的。 不一定高版本一定 就没问题 低版本就不行的。 这一块 还是需要不停的学习与提高解决。
文章目录
原文:你所不知道的C和C++运行库
转载后只做了格式上的编辑,原文如下:
周五晚,小雨,少见的未加班。无聊,遂准备写一篇博客,介绍一下C和C++运行库,只因发现工作几年的人对此一知半解的大有人在。
在使用VC构建项目时,经常会遇到下面的链接错误:

初学者面对这些错误常常不知所错:libcmt.lib是什么东西?msvcrtd.dll又是干吗用的?在使用VC++时我们也常常对下面的运行库配置项感到疑惑,它们到底究竟是什么意思呢?甚至一些工作了很多年的程序员也对此一知半解。今天让我们来了解一下它们。

从C和C++运行库说起
为了提高C语言的开发效率,C标准定义了一系列常用的函数,称为C库函数。C标准仅仅定义了函数原型,并没有提供实现。因此这个任务留给了各个支持C语言标准的编译器。每个编译器通常实现了标准C的超集,称为C运行时库(C Run Time Libray) ,简称CRT。对于VC++编译器来说,它提供的CRT库支持C标准定义的标准C函数,同时也有一些专门针对windows系统特别设计的函数。
与C语言类似,C++也定义了自己的标准,同时提供相关支持库,我们把它称为C++运行时库或C++标准库。
由于C++对C的兼容性,C++标准库包括了C标准库,除此之外还包括IO流和标准模板库STL。
VC++在何处实现C和C++运行库
VC++完美的支持C和C++标准,因此也就按照C和C++的标准定义的函数原型实现了上述运行时库。为了方便有不同需求的客户的使用,VC++分别实现了动态链接库DLL版本和静态库LIB版本。同时为了支持程序调试且不影响程序的性能,又分别提供了对应的调试版本。调试版本的名称在Release版本名称后添了字母d。
对于C运行时库CRT,VC6.0、VC2005、VC2008和VC2010均提供了DLL版本和LIB版本。上述各个编译器提供的LIB版的CRT库,均实现在libcmt.lib。对应的调试版名称为libcmtd.lib。
而DLL版本名称根据编译器不同而不同,我们可以从名称上加以分辨:
VC6.0使用的CRT库的DLL版本在MSVCRT.DLL中实现, 对应调试版本为MSVCRTD.LIB。VC2005使用的CRT库的DLL版本在MSVCR80.DLL中实现,对应调试版本为MSVCR80.DLL。VC2008使用的CRT库的DLL版本在MSVCR90.DLL中实现,对应调试版本为MSVCR90D.DLL。VC2010使用的CRT库的DLL版本在MSVCR100.DLL中实现,对应调试版本为MSVCR100D.DLL。
C++标准兼容C标准,但VC各版本将C++编译器使用的C标准库与C编译器使用的C运行库一起实现,它们使用相同的运行库。
对于C++标准库中的IO流和STL,VC6.0、VC2005、VC2008和VC2010也提供了DLL版本和LIB版本。
LIB版均实现在libcpmt.lib中,对应的调试版本为libcpmtd.lib。
不同版本的编译器实现的DLL也不相同:
VC6.0使用的C++类库的 DLL版本在MSVCP60.DLL中实现, 对应调试版本为MSVCP60D.LIB。VC2005使用的C++类库的DLL版本在MSVCP80.DLL中实现,对应调试版本为MSVCP80.DLL。VC2008使用的C++类库的 DLL版本在MSVCP90.DLL中实现,对应调试版本为MSVCP90D.DLL。VC2010使用的C++类库的DLL版本在MSVCP100.DLL中实现,对应调试版本为MSVCP100D.DLL。
在各个版本的编译器中,我们可以通过配置选项来设置程序使用的C和C++运行时库的类型。如下图(其他版本编译器大同小异):

MT选项:链接LIB版的C和C++运行库。在链接时就会在将C和C++运行时库集成到程序中成为程序中的代码,程序体积会变大。MTd选项:LIB的调试版。MD选项:使用DLL版的C和C++运行库,这样在程序运行时会动态的加载对应的DLL,程序体积会减小,缺点是在系统没有对应DLL时程序无法运行。MDd选项:表示使用DLL的调试版。
在《由使用LeakDialog时遇到的问题而引出的一些分析》这篇文章中的实验一,使用VC6.0的默认配置没有拦截到内存泄露。其原因是VC6.0的控制台项目默认配置是静态链接CRT库(单线程版,后面会介绍)。
动态版(DLL)和静态版(LIB)C和C++运行库的优缺点
因为静态版必须把C和C++运行库复制到目标程序中,所以产生的可执行文件会比较大。同时对于使用多个模块的大型软件来说,如果每个模块均选择静态链接C或C++运行库,在程序运行时就会存在多个运行库。在链接时也会出现重复定义的问题,如文章首第一张图所示。
使用DLL版的C和C++运行库,程序在运行时动态的加载对应的DLL。程序体积变小,但一个很大的问题就是一旦找不到对应DLL,程序将无法运行。假设使用VC6.0并选择使用MD选项构建,那么当用户使用VC2005来使用这个DLL时很可能出现找不到MSVCRT.DLL或MSVCP60.DLL的情况。
在这里介绍一个很好的工具:Dependency Walker,可以用来分析DLL的依赖关系,同时查看DLL导出的函数,使用方法请Google。
使用该工具打开MSVCRT.DLL,如下图:

我们可以在其中找到我们经常使用使用的C函数,如printf ,getchar,malloc等。
打开MSVCP100.DLL,也可以找到这些C函数:

在开发的过程中我们也会遇到如下图的链接错误,LIBCD.lib究竟是何方神圣呢?

它其实是LIBC.lib的调试版,而LIBC.lib是只有在VC6.0才会使用的静态库,该库是CRT的单线程版,用于支持单线程版本的CRT。VC2005等更高版本的编译器已经不再提供单线程版本,转而使用多线程版的MSVCR80.DLL或libcmt.lib。
当遇到上述符号定义冲突的链接错误时,可以选择忽略libcd.lib。
2014.2.28 于浙江杭州
[转帖]你所不知道的C和C++运行库的更多相关文章
- 你所不知道的C和C++运行库 标签: vc 2017-05-26 10:33 41人阅读 评论(0) 收藏
在使用vs2013调用vc2005编译出的dll时出现错误,遂将源程序用vs2013编译出dll,再用vs2013调用错误消失,不解.寻找原因时有人说"VC库版本不一样",故查找C ...
- [转帖]QC 和 PD:关于你所不知道的快充
QC 和 PD:关于你所不知道的快充 http://www.sohu.com/a/276214250_465976 2018-11-18 06:02 当我们使用支持 PD 或者 QC 快充协议的电源适 ...
- 你所不知道的setInterval
在你所不知道的setTimeout记载了下setTimeout相关,此篇则整理了下setInterval:作为拥有广泛应用场景(定时器,轮播图,动画效果,自动滚动等等),而又充满各种不确定性的这set ...
- 你所不知道的setTimeout
JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.它们向任务队列添加定时任务.初始接触它的人都觉得好简单 ...
- 你真的会玩SQL吗?你所不知道的 数据聚合
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你所不知道的linq(二)
上一篇说了from in select的本质,具体参见你所不知道的linq.本篇说下from...in... from... in... select 首先上一段代码,猜猜结果是什么? class P ...
- 你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧
目前SQL Server数据库作为微软一款优秀的RDBMS,其本身启动的时候是很少出问题的,我们在平时用的时候,很少关注起启动过程,或者很少了解其底层运行过程,大部分的过程只关注其内部的表.存储过程. ...
- 你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)
前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程, ...
- Android中Context详解 ---- 你所不知道的Context
转自:http://blog.csdn.net/qinjuning/article/details/7310620Android中Context详解 ---- 你所不知道的Context 大家好, ...
随机推荐
- 《生命》第三集:Mammals (哺乳动物)
南极零下四十度的情况下,威德尔海豹能深潜到冰下捕食,并且教自己的小宝宝如何下水,看了这个才知道,海豹居然是哺乳动物,小海豹看着挺萌的. 长鼻鼩是一种很活跃的生物,而且会自己设计路线,建立迷宫,帮助自己 ...
- 【漫画解读】HDFS存储原理
根据Maneesh Varshney的漫画改编,以简洁易懂的漫画形式讲解HDFS存储机制与运行原理,非常适合Hadoop/HDFS初学者理解. 一.角色出演 如上图所示,HDFS存储相关角色与功能如下 ...
- 微信小程序多层嵌套循环,二级数组遍历
小程序中的遍历循环类似于angularJS的遍历. 二级数组遍历有一个坑.二级遍历wx:for循环的时候,需要注意.(代码如下) JS代码: data: { groups: [ [ { title: ...
- Java基础知识点(二)
前言:Java的基础知识点不能间断. 1.Array和ArrayList的区别 关于Array的用法,参看:http://blog.csdn.net/b_11111/article/details/5 ...
- windows通过node环境搭建安装npm,cnpm,vue-cli
1首先下载node,官网地址:https://nodejs.org/en/ 左边是稳定版,右边是最新版,安装过程一样,我选择的是稳定版. 按照步骤一步一步的安装就行,注意路径就可以了. 友情链接:ht ...
- ASP.NET API Helper Page 创建并生成相关帮助文档
创建API项目 修改原工程文件,该行为是为了避免和引入第三方API工程文件冲突 修改发布设置 引入需要生成文档的相关文件,将第三方API依赖的相关文件(XML文件非常重要,是注释显示的关键),复制到文 ...
- Redo丢失的4种情况及处理方法
这篇文章重点讨论Redo丢失的几种情况,及每种情况的处理方法. 一.说明:1.以下所说的当前日志指日志状态为CURRENT,ACTIVE,非当前日志指日志状态为INACTIVE2.不用考虑归档和非归档 ...
- java中Set的用法
Set集合的特点: 不能存储相同的元素. 同时因为其是一个抽象的接口:所以不能直接实例化一个set对象.(Set s = new Set() )错误 该接口主要继承于Collections接口,所以具 ...
- C# — 创建Windows服务
以前从来没有接触过C#,对Windows服务也完全不了解,今天通过使用VS2017创建了一个Windows服务,并进行了安装和卸载,目前也是一知半解的地步,简单的做个笔记记录一下,也算是复习了吧. 第 ...
- 总结一下linux中的分段机制
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 这篇文章主要说一下linux对于分段机制的处理,虽然都说linux不使用分段机制,但是分段机制属于CPU的一个功 ...