CRT

当C Runtime函数库于20世纪70年代产生出来时,PC的内存容量还很小,多任务是个新奇观念,更别提什么多线程了。因此以当时产品为基础所演化的C Runtime函数库在多线程(multithreaded)的表现上有严重问题,无法被多线程程序使用。
利用各种同步机制(synchronous mechanism)如critical section、mutex、semaphore、event,可以重新开发一套支持多线程的runtime函数库。问题是,加上这样的能力,可能导致程序代码大小和执行效率都遭受不良波及──即使你只激活了一个线程。
Visual C++ 的折衷方案是提供两种版本的C Runtime函数库。一种版本给单线程程序使用,一种版本给多线程程序使用。多线程版本的重大改变是:第一,变量如errno现在变成每个线程各拥有一个。第二,多线程版中的数据结构以同步机制加以保护。

Visual C++ 一共有六个C Runtime函数库产品供你选择:

◆   Single-Threaded(static)            libc.lib             898,826

◆   Multithreaded(static)              libcmt.lib           951,142

◆   Multithreaded DLL                    msvcrt.lib           5,510,000

◆   Debug Single-Threaded(static)      libcd.lib            2,374,542

◆   Debug Multithreaded(static)        libcmtd.lib          2,949,190

◆   Debug Multithreaded DLL              msvcrtd.lib          803,418

Visual C++ 编译器提供下列选项,让我们决定使用哪一个C Runtime函数库:

◆   /ML          Single-Threaded(static)

◆   /MT          Multithreaded(static)

◆   /MD          Multithreaded DLL(dynamic import library)

◆   /MLd         Debug Single-Threaded(static)

◆   /MTd         Debug Multithreaded(static)

◆   /MDd         Debug Multithreaded DLL(dynamic import library)


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chuajiang/archive/2007/06/21/1660475.aspx

 

MSVC CRT

MSVC CRT是微软发布的c运行时,一直伴随着不同版本的Visual C++发布的MSVC CRT(Microsoft Visual C++ C Runtime)倒看过去更加有序一些。从1992年最初的Visual C++ 1.0版开始,一直到现在的Visual C++ 9.0(又叫做Visual C++ 2008),MSVC CRT也从1.0版发展到了9.0版。

同一个版本的MSVC CRT根据不同的属性提供了多种子版本,以供不同需求的开发者使用。按照静态/动态链接,可以分为静态版和动态版;按照单线程/多线程,可以分为单线程版和多线程版;按照调试/发布,可分为调试版和发布版;按照是否支持C++分为纯C运行库版和支持C++版;按照是否支持托管代码分为支持本地代码/托管代码和纯托管代码版。这些属性很多时候是相互正交的,也就是说它们之间可以相互组合。比如可以有静态单线程纯C纯本地代码调试版;也可以有动态的多线程纯C纯本地代码发布版等。但有些组合是没有的,比如动态链接版本的CRT是没有单线程的,所有的动态链接CRT都是多线程安全的。

这样的不同组合将会出现非常多的子版本,于是微软提供了一套运行库的命名方法。这个命名方法是这样的,静态版和动态版完全不同。静态版的CRT位于MSVC安装目录下的lib/,比如Visual C++ 2008的静态库路径为“Program Files/Microsoft Visual Studio 9.0/VC/lib”,它们的命名规则为:

libc [p] [mt] [d] .lib

l           p 表示 C Plusplus,即C++标准库。

l           mt表示 Multi-Thread,即表示支持多线程。

l           d 表示 Debug,即表示调试版本。

比如静态的非C++的多线程版CRT的文件名为libcmtd.lib。动态版的CRT的每个版本一般有两个相对应的文件,一个用于链接的.lib文件,一个用于运行时用的.dll动态链接库。它们的命名方式与静态版的CRT非常类似,稍微有所不同的是,CRT的动态链接库DLL文件名中会包含版本号。比如Visual C++ 2005的多线程、动态链接版的DLL文件名为msvcr90.dll(Visual C++ 2005的内部版本号为8.0)。表11-1列举了一些最常见的MSVC CRT版本(以Visual C++ 2005为例)。

表11-1

 

文件名

相关的DLL

属性

编译器选项

预编译宏

libcmt.lib

多线程,静态链接

/MT

_MT

msvcrt.lib

msvcr80.dll

多线程,动态链接

/MD

_MT, _DLL

libcmtd.lib

多线程,静态链接,调试

/MTd

_DEBUG, _MT

msvcrtd.lib

msvcr90d.dll

多线程,动态链接,调试

/MDd

_DEBUG, _MT, _DLL

msvcmrt.lib

msvcm90.dll

托管/本地混合代码

/clr

 

msvcurt.lib

msvcm90.dll

纯托管代码

/clr:pure

 

 

自从Visual C++ 2005(MSVC 8.0)以后,MSVC不再提供静态链接单线程版的运行库(LIBC.lib、LIBCD.lib),因为据微软声称,经过改进后的新的多线程版的C运行库在单线程的模式下运行速度已经接近单线程版的运行库,于是没有必要再额外提供一个只支持单线程的CRT版本。

默认情况下,如果在编译链接时不指定链接哪个CRT,编译器会默认选择LIBCMT.LIB,即静态多线程CRT,Visual C++ 2005之前的版本会选择LIBC.LIB,即静态单线程版本。关于CRT的多线程和单线程的问题,我们在后面的章节还会再深入分析。

除了使用编译命令行的选项之外,在Visual C++工程属性中也可以设置相关选项。如图11-9所示。

 

 

图11-9  Visual C++ 2003 .NET工程属性的截图

我们可以从图11-9中看到,除了多线程库以外,还有单线程静态/ML、单线程静态调试/MLd的选项。

C++ CRT
表11-1中的所有CRT都是指C语言的标准库,MSVC还提供了相应的C++标准库。如果你的程序是使用C++编写的,那么就需要额外链接相应的C++标准库。这里“额外”的意思是,如表11-2所列的C++标准库里面包含的仅仅是C++的内容,比如iostream、string、map等,不包含C的标准库。

表11-2

文件名

相应DLL

属性

编译选项

宏定义

LIBCPMT.LIB

多线程,静态链接

/MT

_MT

MSVCPRT.LIB

MSVCP90.dll

多线程,动态链接

/MD

_MT, _DLL

LIBCPMTD.LIB

多线程,静态链接,调试

/MTd

_DEBUG, _MT

MSVCPRTD.LIB

MSVCP90D.dll

多线程,动态链接,调试

/MDd

_DEBUG, _MT, _DLL

 
当你在程序里包含了某个C++标准库的头文件时,MSVC编译器就认为该源代码文件是一个C++源代码程序,它会在编译时根据编译选项,在目标文件的“.drectve”段(还记得第2章中的DIRECTIVE吧?)相应的C++标准库链接信息。比如我们用C++写一个“Hello World”程序:

// hello.cpp

#include <iostream>

int main()

{

    std::cout << "Hello world" << std::endl;

    return 0;

}

然后将它编译成目标文件,并查看它的“.drectve”段的信息:

cl /c hello.cpp

dumpbin /DIRECTIVES hello.obj

Microsoft (R) COFF/PE Dumper Version 9.00.21022.08

Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file msvcprt.obj

File Type: COFF OBJECT

   Linker Directives

   -----------------

   /DEFAULTLIB:"libcpmt"

   /DEFAULTLIB:"LIBCMT"

   /DEFAULTLIB:"OLDNAMES"

cl /c /MDd hello.cpp

dumpbin /DIRECTIVES hello.obj

Microsoft (R) COFF/PE Dumper Version 9.00.21022.08

Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file msvcprt.obj

File Type: COFF OBJECT

   Linker Directives

   -----------------

   /manifestdependency:"type='win32'

   name='Microsoft.VC90.DebugCRT'

   version='9.0.21022.8'

   processorArchitecture='x86'

   publicKeyToken='1fc8b3b9a1e18e3b'"

   /DEFAULTLIB:"msvcprtd"

   /manifestdependency:"type='win32'

   name='Microsoft.VC90.DebugCRT'

   version='9.0.21022.8'

   processorArchitecture='x86'

   publicKeyToken='1fc8b3b9a1e18e3b'"

   /DEFAULTLIB:"MSVCRTD"

   /DEFAULTLIB:"OLDNAMES"

可以看到,hello.obj须要链接libcpmt.lib、LIBCMT.lib和OLDNAMES.lib。当我们使用“/MDd”参数编译时,hello.obj就需要msvcprtd.lib、MSVCRTD.lib和OLDNAMES.lib,除此之外,编译器还给链接器传递了“/manifestdependency”参数,即manifest信息。

Q&A

Q:如果一个程序里面的不同obj文件或DLL文件使用了不同的CRT,会不会有问题?

A:这个问题实际上分很多种情况。如果程序没有用到DLL,完全静态链接,不同的obj在编译时用到了不同版本的静态CRT。由于目前静态链接CRT只有多线程版,并且如果所有的目标文件都统一使用调试版或发布版,那么这种情况下一般是不会有问题的。因为我们知道,目标文件对静态库引用只是在目标文件的符号表中保留一个记号,并不进行实际的链接,也没有静态库的版本信息。

       但是,如果程序涉及动态链接CRT,这就比较复杂了。因为不同的目标文件如果依赖于不同版本的msvcrt.lib和msvcrt.dll,甚至有些目标文件是依赖于静态CRT,而有些目标文件依赖于动态CRT,那么很有可能出现的问题就是无法通过链接。链接器对这种情况的具体反应依赖于输入目标文件的顺序,有些情况下它会报符号重复定义错误:

       MSVCRTD.lib(MSVCR80D.dll) : error LNK2005: _printf already defined in LIBCMTD.lib (printf.obj)

       但是有些情况下,它会使链接顺利通过,只是给出一个警告:

       LINK : warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of other libs; use /NODEFAULTLIB:library

       如果碰到上面这种静态/动态CRT混合的情况,我们可以使用链接器的/NODEFAULTLIB来禁止某个或某些版本的CRT,这样一般就能使链接顺利进行。

       最麻烦的情况应该属于一个程序所依赖的DLL分别使用不同的CRT,这会导致程序在运行时同时有多份CRT的副本。在一般情况下,这个程序应该能正常运行,但是值得注意的是,你不能够在这些DLL之间相互传递使用一些资源。比如两个DLL A和B分别使用不同的CRT,那么应该注意以下问题:

     l     不能在A中申请内存然后在B中释放,因为它们分属于不同的CRT,即拥有不同的堆,这包括C++里面所有对象的申请和释放;

     l     在A中打开的文件不能在B中使用,比如FILE*之类的,因为它们依赖于CRT的文件操作部分。

       还有类似的问题,比如不能相互共享locale等。如果不违反上述规则,可能会使程序发生莫名其妙的错误并且很难发现。

       防止出现上述问题的最好方法就是保证一个工程里面所有的目标文件和DLL都使用同一个版本的CRT。当然有时候事实并不能尽如人意,比如很多时候当我们要用到第三方提供的.lib或DLL文件而对方又不提供源代码时,就会比较难办。

       Windows系统的system32目录下有个叫msvcrt.dll的文件,它跟msvcr90.dll这样的DLL有什么区别?

Q:为什么我用Visual C++ 2005/2008编译的程序无法在别人的机器上运行?

A:因为Visual C++ 2005/2008编译的程序使用了manifest机制,这些程序必须依赖于相对应版本的运行库。一个解决的方法就是使用静态链接,这样就不需要依赖于CRT的DLL。另外一个解决的方法就是将相应版本的运行库与程序一起发布给最终用户。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509441.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java多线程笔记补充之线程的生命周期

多线程通信的时候很容易造成死锁,死锁无法解决,只能避免: 当A线程等待由B线程持有的锁,而B线程正在等待A线程持有的锁时,发生死锁现象,JVM不检测也不试图避免这种情况,所以程序员必须保证不导致死锁. 避免死锁法则: 当多个线程都要访问共享的资源A,B,C时,保证每一个线程都按照…

java多线程笔记补充之 线程控制操作

线程休眠:让执行的线程暂停一段时间&#xff0c;进入计时等待状态。 方法:staticvoid sleep(long millis) 调用sleep后&#xff0c;当前线程放弃CPU,在指定时间段之内&#xff0c;sleep所在线程不会获得执行的机会。 此状态下的线程不会释放同步锁/同步监听器. 该方法更多的用…

java5新特性静态引用、foreach、自动装箱和泛型枚举以及可变参数的总结

静态引用 导入(import)表示去找哪一个类&#xff0c;去哪一个包下去找哪些被使用到的类。 在java中有一个语言核心包&#xff1a;java.lang. 使用java.lang包中的API&#xff0c;不需要引用&#xff0c;直接能找到&#xff0c;但是&#xff0c;如果我们使用到的API不呼吁java.l…

java8新特性lambda表达式、函数式编程、方法引用和接口默认方法以及内部类访问外部变量

一提到java是一种什么语言&#xff1f; 大多数人肯定异口同声的说是一门面向对象的语言&#xff0c;这种观点从我们开始学java就已经根深蒂固了&#xff0c;但是学到java8新特性函数式编程的时候&#xff0c;我才知道java并不是纯面向对象的语言。 lambda表达式的详细教程 lam…

javaWeb回忆思维导图

出处&#xff1a;https://blog.csdn.net/jackfrued/article/details/42617675 https://www.cnblogs.com/xieyupeng/p/6961667.html

Spring详细导包截图以及IOC和DI思想

思想 IOC DI Spring中的工厂(容器) ApplicationContext&#xff1a; BeanFactory(过时)&#xff1a; BeanFactory和ApplicationContext区别 BeanFactory&#xff1a; 1.Spring原始接口&#xff0c;针对原始接口实现类功能较为单一 2.是在getBean的时候才会生成类的实例…

毕业两年的我--奋斗中的程序员

又到一年毕业季&#xff0c;不知不觉&#xff0c;自己毕业快两年了&#xff0c;在这两年中&#xff0c;从一位小白程序员蜕化到现在的拥有两年经验的C程序员&#xff0c;这两年里面&#xff0c;不敢说成长有多快&#xff0c;进步有多大&#xff0c;但是感觉很踏实&#xff0c;每…

spring配置讲解

Bean元素 Bean元素进阶 scope属性&#xff1a; 1.singleton(默认值):单例对象.被标识为单例的对象在spring容器中只会存在一个实例 2.prototype:多例原型.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.整合struts2时,ActionBean必须配置为多例的. 3.request…

情商低的七种表现,你占了几个

你身边有没有这样的人&#xff1a;大家刚刚还聊的热火朝天&#xff0c;却在他进门的瞬间&#xff0c;整场“冷冻结冰”&#xff0c;大家都各忙各的&#xff0c;避免与他交流。我们称这样的人为“冷场帝”。那么&#xff0c;“冷场帝”是如何养成的&#xff1f;这样的人通常情商…

spring属性注入

注入方式 set方法注入 构造函数注入 p名称空间注入 spel注入(#表示理解为引用) 练习代码&#xff1a; <!-- 第二天 set注入 index:索引 ref:引用对象 type:参数类型--><bean name"person" class"com.spring.bean.Person"><constructor-a…

你所不知道的C和C++运行库

转自&#xff1a;http://blog.csdn.net/ithzhang/article/details/20160009 你所不知道的C和C运行库    周五晚&#xff0c;小雨&#xff0c;少见的未加班。无聊&#xff0c;遂准备写一篇博客&#xff0c;介绍一下C和C运行库&#xff0c;只因发现工作几年的人对此一知半解的…

使用注解配置spring如@Compnent、@Service、@Consroller、@scope和@value的使用

步骤 1.导包42spring-aop如图&#xff1a;为学习到该阶段需要用到的包(里面的aoptest是spring和junit整合测试的时候用到的)2.为主配置文件引入新的命名空间(约束)3.开启使用注解代理配置文件<?xml version"1.0" encoding"UTF-8"?> <beans xmln…

java实现深度优先搜索 (DFS) 算法

度优先搜索&#xff08;Depth First Search&#xff0c;DFS&#xff09;算法是一种用于遍历或搜索图或树的算法。这种算法从一个节点开始&#xff0c;沿着一条路径尽可能深地搜索&#xff0c;直到遇到不能继续前进的节点时返回上一个节点&#xff0c;然后继续搜索其他路径。具体…

spring整合JDBC

文章目录spring提供了很多模板整合Dao技术spring中提供了一个可以操作数据库的对象.对象封装了jdbc技术.如何用Spring中的jdbc模板对数据库操作&#xff1a;spring配置进阶内容JDBCDaoSupport的使用spring提供了很多模板整合Dao技术 因为在jdbc、Hibernate、Mybatis中都有对数据…

spring中aop事务

文章目录事务为什要用到Spring中AOP事务事物的特性 ACID事务并发问题事务的隔离级别spring事务管理事务操作事务操作对象spring管理事务的属性介绍spring管理事务方式编码式xml配置(aop)注解配置Transactional注解在方法上添加Transactional注解在类上添加实际案例xml配置注入a…

Mybatis介绍、jdbc操作数据库原始写法以及Mybatis架构

文章目录Mybatis介绍jdbc操作数据库原生写法使用jdbc编程问题总结Mybatis架构Mybatis介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code&#xff0c;并且改名为MyBatis 。2013年11月迁移到Github。 MyBatis是一个…

利用Mybatis写第一个数据库操作的程序

文章目录mybatis下载业务需求环境搭建加入配置文件创建pojosql映射文件加载映射文件实现根据id查询用户测试程序&#xff1a;效果mybatis下载 mybaits的代码由github.com管理 下载地址&#xff1a;https://github.com/mybatis/mybatis-3/releases 下载的mybatis文件如下&#…

利用Mybatis对数据库进行增删改查操作

文章目录mybatis模糊查找先来了解一下 #{}和${}的使用parameterType和resultType的使用selectOne和selectList的使用mysql自增主键返回方法一&#xff1a;mysql的函数函数返回方法二&#xff1a;定义useGeneratedKeys为true返回Mysql使用 uuid实现主键看到UUID和自增长的id想必…

聚合和组合的关系

转自&#xff1a;http://www.blogjava.net/lukangping/archive/2010/08/01/327693.html 记得在当时学习uml总是不好分清聚合与组合的关系&#xff0c;找工作时特地复习了这块的内容&#xff0c;结果正巧被面试官问道&#xff0c;这两天又在搞这块的内容&#xff0c;对聚合与组合…

关联和依赖的区别

最近研究设计模式&#xff0c;看类图有点发虚&#xff01;有些关系搞的不是很清楚。所以整理一下&#xff1a; 类与类之间由弱到强关系是: 没关系 > 依赖 > 关联 > 聚合 > 组合。 类和类之间八竿子打不着那就是没关系&#xff0c;这个没啥歧义。 依赖(dependenc…