程序同时使用微软的多个C运行库的风险

来源:互联网 发布:js中换行符是哪个 编辑:程序博客网 时间:2024/05/01 09:42

        同时使用微软的多个C运行库的风险

            

 Microsoft的Visual C++是Windows下使用最广的编译器,历史悠久,目前的最新版本是VC2008。VC有多个版本,每个版本都附带一个C运行库。从VC6开始附带的运行库如下:

   VC6                     msvcrt.dll    

   VC7(VC 2002)     msvcrt7.dll

   VC7.1(VC2003)   msvcrt71.dll

   VC8(VC2005)      msvcrt80.dll

   VC9(VC2008)      msvcrt90.dll

msvcrt.dll后来由Windows自带,成为了Windows系统的一部分,描述也成了“Windows NT CRT DLL”。

 

假如一个程序在VC2008下面开发,但是它依赖于某些第三方动态库,这些第三方库由VC6编译,这样程序就会同时依赖于msvcrt.dll和msvcrt90.dll这两个C运行库。这样做有什么风险呢?程序中很多对象、资源都是由C运行库维护的(那些不依赖于C运行库的程序例外),比如内存(通过malloc申请的内存)、文件指针(FILE*)、环境变量。程序依赖多个C运行库,进程中就有C运行库的多个实例,这些个不同C运行库维护的对象、资源是不能混用的,否则就会导致严重的错误。比如通过msvcrt.dll打开的文件指针传递给msvcr90.dll去读取文件内容。

详情可以参考下面的两个文档:

C Run-Time Libraries http://msdn.microsoft.com/en-us/library/abx4dbyh.aspx

Potential Errors Passing CRT Objects Across DLL Boundaries

http://msdn.microsoft.com/en-us/library/ms235460.aspx

这种情况一定会出问题吗?那到不一定。如果动态库的接口设计者注意到了这个问题,接口设计的比较合理,参数和返回值的类型都比较合理,就不会有问题。

 

另外一种情况与此类似,也会导致多个C运行库实例的出现。那就是:程序中某些库链接到了Debug版本的C运行库,某些库链接到了Release版本的C运行库。

 

对于新版本的VC来说,如果打了补丁后C运行库进行了更新,新的C运行库和旧的也是不同的版本,即使它们名字相同,它们会被放到/WINDOWS/WinSxS下不同的目录中。这种情况也需要谨慎小心,尽量使用同一个补丁版本进行编译,链接到同样版本的运行库。

 

在程序有多个库组成时,用同一个编译器编译,同时保证它们的编译选项尽量一致。这样避免一些莫名其妙错误的发生。

 

同样这个问题在C++运行库中也存在,不再详述。

 

原创粉丝点击