一 产生

运行时库是程序在运行时所需要的库文件,通常以LIB或DLL形式提供。

C运行时库就是C run-time library,诞生于20世纪70年代,是C而非C++语言世界的概念,C程序运行时需要这些库中的函数。

C 语言是所谓的“小内核”语言,就其语言本身来说很小(不多的关键字,程序流程控制,数据类型等)。所以,C语言内核开发出来之后,Dennis Ritchie和Brian Kernighan就用C本身重写了90%以上的UNIX系统函数,并且把其中最常用的部分独立出来,形成头文件和对应的LIBRARY,C运行时库就是这样形成的。

随着C语言的流行,各个C编译器的生产商/个体/团体都遵循老的传统,在不同平台上都有相对应的Standard Library,但大部分实现都是与各个平台有关的。由于各个C编译器对C的支持和理解有很多分歧和微妙的差别,所以就有了ANSI C;ANSI C(主观意图上)详细的规定了C语言各个要素的具体含义和编译器实现要求,引进了新的函数声明方式,同时订立了Standard Library的标准形式。所以C运行时库由编译器生产商提供。至于由其他厂商/个人/团体提供的头文件和库函数,应当称为第三方C运行库(Third
party C run-time libraries)。

二 发展

到了 C++ 世界里,有另外一个概念:Standard C++ Library,它包括了上面所说的 C run-time library 和 STL。包含 C run-time library 的原因很明显,C++ 是 C 的超集,没有理由再重新来一个 C++ run-time library. VC针对C++ 加入的Standard C++ Library主要包括:LIBCP.LIB,
LIBCPMT.LIB和 MSVCPRT.LIB

C运行库刚诞生的时候,程序世界还很单纯,应用程序都是单线程的,多任务或多线程机制在此时还属于新观念。所以这个时期的C运行时库都是单线程的。

随着操作系统多线程技术的发展,最初的C运行时库无法满足程序的需求,出现了严重的问题。C运行时库使用了多个全局变量(例如errno)和静态变量,这可能在多线程程序中引起冲突。假设两个线程都同时设置errno,其结果是后设置的errno会将先前的覆盖,用户得不到正确的错误信息。

因此,Visual C++提供了两种版本的C运行时库。一个版本供单线程应用程序调用,另一个版本供多线程应用程序调用。多线程运行时库与单线程运行时库有两个重大差别:

(1)类似errno的全局变量,每个线程单独设置一个。这样从每个线程中可以获取正确的错误信息。

(2)多线程库中的数据结构以同步机制加以保护。     这样可以避免访问时候的冲突。

Visual C++提供的多线程运行时库又分为静态链接库和动态链接库两类,而每一类运行时库又可再分为debug版和release版,因此Visual C++共提供了6个运行时库。如下表:(单线程和多线程都有debug版和release版;只有多线程才有静态链接库和动态链接库之分)

C运行时库 库文件
Single thread(static link) libc.lib
Debug single thread(static link) libcd.lib
MultiThread(static link) libcmt.lib
Debug multiThread(static link) libcmtd.lib
MultiThread(dynamic link) msvcrt.lib(导入库)
Debug multiThread(dynamic link) msvcrtd.lib(导入库)

三 C运行库的作用

(1)C运行时库包含了C程序运行的最基本和最常用的函数(如memcpy、printf、malloc等)。 

(2)C运行时库除了给我们提供必要的库函数调用之外,它提供的另一个最重要的功能是为应用程序添加启动函数。C运行时库启动函数的主要功能为进行程序的初始化,对全局变量进行赋初值,加载用户程序的入口函数。

不采用宽字符集的控制台程序的入口点为mainCRTStartup(void)。下面我们以该函数为例来分析运行时库究竟为我们添加了怎样的入口程序。这个函数在crt0.c中(crt0.c是静态链接CRT,动态链接则为crtexe.c)被定义,下列的代码经过了笔者的整理和简化:

void mainCRTStartup(void) 



int mainret; 

/*获得WIN32完整的版本信息*/ 

_osver = GetVersion(); 

_winminor = (_osver >> 8) & 0x00FF ; 

_winmajor = _osver & 0x00FF ; 

_winver = (_winmajor << 8) + _winminor; 

_osver = (_osver >> 16) & 0x00FFFF ; 

_ioinit(); /* initialize lowio */ 



_acmdln = (char *) GetCommandLineA(); /* 获得命令行信息 */ 

_aenvptr = (char *) __crtGetEnvironmentStringsA(); /* 获得环境信息 */ 

_setargv(); /* 设置命令行参数 */ 

_setenvp(); /* 设置环境参数 */ 

_cinit(); /* C数据初始化:全局变量初始化,就在这里!*/ 

__initenv = _environ; 

mainret = main( __argc, __argv, _environ ); /*调用main函数*/ 

exit( mainret ); 

}

从以上代码可知,运行库在调用用户程序的main或WinMain函数之前,进行了一些初始化工作。初始化完成后,接着才调用了我们编写的main或WinMain函数。只有这样,我们的C语言运行时库和应用程序才能正常地工作起来。

你写的程序可以没有math库,程序照样运行,只是不能处理复杂的数学运算,不过如果没有了C run-time库,main()就不会被调用,exit()也不能被响应。

除了crt0.c外,C运行时库中还包含wcrt0.c、 wincrt0.c、wwincrt0.c三个文件用来提供初始化函数。wcrt0.c是crt0.c的宽字符集版,wincrt0.c中包含windows应用程序的入口函数,而wwincrt0.c则是wincrt0.c的宽字符集版。

Visual C++的运行时库源代码缺省情况下不被安装。如果您想查看其源代码,则需要重装Visual C++,并在重装在时选中安装运行库源代码选项。

四 各种C运行时库的区别

编译器链接选项:

Visual C++编译时到底哪个C运行时库联入程序取决于编译选项,选项告诉编译器应用程序想使用什么版本的C标准程序库。与标准程序库有关的选项:/ML、/MLd、/MT、/MTd、/MD、/MDd

/ML对应单线程静态版的标准程序库(libc.lib); 

/MT对应多线程静态版标准库(libcmt.lib),此时编译器会自动定义_MT宏; 

/MD对应多线程DLL版(导入库msvcrt.lib,DLL是msvcrt.dll),编译器自动定义_MT和_DLL两个宏。

后面加d的选项都会让编译器自动多定义一个_DEBUG宏,表示要使用对应标准库的调试版,因此: 

/MLd对应调试版单线程静态标准库(libcd.lib); 

/MTd对应调试版多线程静态标准库(libcmtd.lib); 

/MDd对应调试版多线程DLL标准库(导入库msvcrtd.lib,DLL是msvcrtd.dll)。

VC2005/VC6.0中通过以下方法设置选择哪个C run-time library联入你的程序:

VC2005: To find these options in the development environment, click Project on the Project menu, choose Properties... item. Then click the C/C++ tab,
and click Code Generation in the Category box. See the Runtime Library drop-down box.

VC6.0:To find these options in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation
in the Category box. See the Use Run-Time Library drop-down box.

各种C运行时库的区别:

(1)静态链接的单线程库

静态链接的单线程库只能用于单线程的应用程序,C运行时库的目标代码最终被编译在应用程序的二进制文件中。通过/ML编译选项可以设置Visual C++使用静态链接的单线程库。

(2)静态链接的多线程库

静态链接的多线程库的目标代码也最终被编译在应用程序的二进制文件中,但是它可以在多线程程序中使用。通过/MT编译选项可以设置Visual C++使用静态链接的单线程库。

(3)动态链接的运行时库

动态链接的运行时库将所有的C库函数保存在一个单独的动态链接库MSVCRTxx.DLL中,MSVCRTxx.DLL处理了多线程问题。使用/MD编译选项可以设置Visual C++使用动态链接的运行时库。

/MLd、 /MTd或/MDd选项使用Debug Runtime Library(调试版本的运行时刻函数库),与/ML、/MT或/MD分别对应。Debug版本的Runtime Library包含了调试信息,并采用了一些保护机制以帮助发现错误,加强了对错误的检测,因此在运行性能方面比不上Release版本。

程序运行时,很大一部分时间是在这些运行库里运行。在程序(Release版)被编译时,VC会根据编译选项(单线程、多线程或DLL)自动将相应的运行时库文件(libc.lib、libcmt.lib或Import library msvcrt.lib)链接进来。

注:修改编译选项,将/MD或/MDd改为/MT或/MTd,就实现了对VC运行时库的静态链接,在运行时就不再需要VC的dll了。(静态链接将目标代码直接编译在应用程序的二进制文件中,这样运行时就不需要dll了)

参考

http://blog.chinaunix.net/u2/75914/showart_1861328.html

http://www.99inf.net/SoftwareDev/VC/28090.htm

转自:http://blog.csdn.net/maomaokuaile/article/details/5070320

注:

  • vs2005 call stack

  • kernel32.dll ---> mainCRTStartup ---> main

CRT (C run-time library)的更多相关文章

  1. CRT(C Runtime Library)—— C/C++运行时库

    C runtime library(part of the C standard library) 任何一个 C 程序,它的背后都有一套庞大的代码来进行支撑,使得该程序得以运行在更高级别上,而不必担心 ...

  2. [转帖]运行时库(runtime library)

    运行时库(runtime library) https://blog.csdn.net/xitie8523/article/details/82712105 没学过这些东西 或者当时上课没听 又或者 ...

  3. xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at[转载]

    今天在添加友盟统计的podfile pod install报错了: bogon:Children songximing$ pod install /Library/Ruby/Gems//gems/co ...

  4. IC79620: USER'S ROUTINE MAY BE TERMINATED ABNORMALLY IF SOME SYSTEMROUTINES WERE RUN IN DB2FMP BEFORE

    http://www-01.ibm.com/support/docview.wss?uid=swg1IC79620 APAR status Closed as program error. Error ...

  5. VC-基础:常用的安全CRT函数

    常用的安全CRT函数 安全CRT(C Runtime Library = C运行时间库)函数,是微软公司对C/C++语言的扩展.它在原来函数名后添加了“_s”后缀:一般返回出错代码:并将原来的函数返回 ...

  6. C++ Development Library

    C/C++ 开发库 | C/C++ Development Library 这里收集一些著名的 C/C++ 开发库.SDK.类库.可复用类与结构代码 等信息,列举它们的介绍.参考和网站链接,为各位 C ...

  7. strlen源码剖析(可查看glibc和VC的CRT源代码)

    学习高效编程的有效途径之一就是阅读高手写的源代码,CRT(C/C++ Runtime Library)作为底层的函数库,实现必然高效.恰好手中就有glibc和VC的CRT源代码,于是挑了一个相对简单的 ...

  8. visual studio运行时库MT、MTd、MD、MDd的研究(转载)

    转载:http://blog.csdn.net/ybxuwei/article/details/9095067 转载:http://blog.sina.com.cn/s/blog_624485f701 ...

  9. c#调用c++ dll(一)

    首先来说说c++中的dll 核心的一些知识 比较大的应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作.可能存在一些模块的功能较为通用,在构造其它软件系统时 ...

  10. Win32多线程编程(2) — 线程控制

    Win32线程控制只有是围绕线程这一内核对象的创建.挂起.恢复.终结以及通信等操作,这些操作都依赖于Win32操作系统提供的一组API和具体编译器的C运行时库函数.本篇围绕这些操作接口介绍在Windo ...

随机推荐

  1. mysql数据库外键、主键详解

    一.什么是主键.外键: 关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键 比如  学生表(学号,姓名,性别,班级) 其中每个学生的学 ...

  2. new 在C++ 中的用法

    我对C++一无所知 看参考手册 来看一下参考手册,总共有三种用法 下面是网站上给出的例子 // operator new example #include <iostream> // st ...

  3. js点击复制文本

    // 动态创建 input 元素 var aux = document.createElement("input"); // 获得需要复制的内容 aux.setAttribute( ...

  4. Leetcode590N-ary Tree Postorder TraversalN叉树的后序遍历

    给定一个 N 叉树,返回其节点值的后序遍历. class Node { public: int val; vector<Node*> children; Node() {} Node(in ...

  5. Lavavel 程序报错 MassAssignmentException in Model.php line 452: _token

    Lavarel 用类似于下面命令插入数据时候出错 Comment::create($request->all()) 错误页面截图如下: 错误原因:下面这行代码应该写到对应的Model里面,而不是 ...

  6. H5C3--FileReader和拖拽的应用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. oracle 索引监控

           索引对于在大量数据里检索出少量数据库的查询操作来说是高效的,可是对于DML操作来说.却是负面的:①其对于insert 操作的反面影响最大.该表的索引越多,更新的索引越多,insert 操 ...

  8. Android基础&进阶

    基础总结篇之一:Activity生命周期 基础总结篇之二:Activity的四种launchMode 基础总结篇之三:Activity的task相关 基础总结篇之四:Service完全解析 基础总结篇 ...

  9. BZOJ 3057圣主的考验题解

    老师居然考这么毒瘤的题目!!!!! 很容易想到dp,f[i][j]表示有i个节点,左子树的最深深度为j的方案数 枚举左子树有多少节点然后转移,复杂度为n^3 T飞~ 我们考虑到有深度为h的树的节点有多 ...

  10. iscroll5在使用情况下click事件失效的问题

    转载自:http://www.52html5.com/?p=2618 Bug描述: iOS.android4.4+下不能触发click事件. Bug解决: 调用iscroll插件,增加配置参数:cli ...