• 复杂的C运行时库


    因为各种原因常加一些第三方库到工程中。使用这些库,最好能够自己编译,否则应该真的应该好好检查一下它对C运行时库的依赖情况,否则真的容易出现莫名其名的访存错误。

    总结一下,要检查以下几个方面:

    1. 要检查一下依赖的C runtime lib是debug或release版,不要混用二者。

    2. 检查C runtime lib是单线程版、静态多线程还是动态链版。

    我们先看CRTLib (C运行库):

    msdn 上有这样一段话:

    警告 不要混合使用运行时库的静态版本和动态版本。在一个进程中有多个运行时库副本会导致问题,因为副本中的静态数据不与其他副本共享。链接器禁止在 .exe 文件内部既使用静态版本又使用动态版本链接,但您仍可以使用运行时库的两个(或更多)副本。例如,当与用动态 (DLL) 版本的运行时库链接的 .exe 文件一起使用时,用静态(非 DLL)版本的运行时库链接的动态链接库可能导致问题。(还应该避免在一个进程中混合使用这些库的调试版本和非调试版本)。

    还有这样一张表:

    Reusable Library                Switch    Library    Macro(s) Defined
    ----------------------------------------------------------------
    Single Threaded                     /ML       LIBC               (none)
    Static MultiThread                  /MT       LIBCMT         _MT
    Dynamic Link (DLL)              /MD       MSVCRT        _MT and _DLL
    Debug Single Threaded           /MLd      LIBCD          _DEBUG
    Debug Static MultiThread        /MTd      LIBCMTD    _DEBUG and _MT
    Debug Dynamic Link (DLL)    /MDd      MSVCRTD    _DEBUG, _MT, and _DLL

    这张表列出了Windows下有六种类型CRTLib(C运行库),它们是使用不同的switch生成的,这些switch通过宏起作用。

    其中MT和MD都适用于多线程,其区别是:
    1. MT为静态链接CRT,这样编译出来exe是自包含的,所以会相对大一些,但运行时不用再load CRT库。
    2. MD为动态链接CRT,编译出来exe会小一些,运行时需要load CRT,性能有一点点损失。

    任何工程都应该使用同样的CRT Library。即要么都是/ML,要么都是/MTD, 如此类推。 如果一个程序中混合使用不同类型的CRT,有时可以通过link,这样会存在不同CRT的copy,并会导致内存,比如:
    1. 在一个lib中new出来内存,在另一个lib中delete,会crash。
    2. 不能在多个lib中共享file handle,理由同上。
    3. 一个lib中设置locale(本地化有关),不能在另一个lib中起作用。

    其实对于Standard C++ Library也有类似的问题,我们这里同样列出一张表:

    image

    当链接程序时,一个C运行库会根据switch与你的程序链接,这是默认行为;但是如果你包含了C++标准头文件,比如<ios>那么Standard C++ Library会被链接进来。

    msvcrt.dll 与 msvcr71.dll

    还有一个比较常见的dll叫msvcr71.dll,将之与msvcrt.dll放在一起说。msvcrt.dll 是系统的一部分,它是为将来系统级组件预留的。我们的程序应该使用、发布的是msvcr71.dll,而且当发布时,最好把这个dll放在程序的目录下而非替换系统目录下的同名dll.

    目前而言,这两个dll还是比较混乱的,如果你手上有个比较老的库依赖mscvrt.lib,那么其中依赖的dll可能是mscrt.dll,而如果你重新编译这个库的话会发现c运行库的依赖变成了mscrt71.dll。而把mscrt.dll和mscrt71.dll混用也是很不好的,同样可能出现我们上而引用的msdn那段话中讲的问题。

    所以现在我在选择第三方库时会比较注意尽量选择开源的库;如果需要加入其他人编译的库,也会用比如dependence walker这样的工具先检查一下对C运行时的依赖情况。

    推而广之一下,其实不仅C运行时库了,如果两个第三方库共同依赖了另外一个库,那么这个库的版本也应该被检查。

    博客园上也还有不少文章与本文讲述的内容相近,比如以下两篇:

    1. http://www.cnblogs.com/diyunpeng/archive/2011/06/16/2083085.html

    2. http://www.cnblogs.com/Frodo/archive/2008/02/04/1064267.html

  • 相关阅读:
    JSF
    filter用户例子
    分析LogFilter
    理解session
    了解xml文件
    软件工程期末项目总结
    阅《软件工程》——之感
    自我介绍
    期末课程设计《天猫后台管理系统》
    JSON
  • 原文地址:https://www.cnblogs.com/justin_s/p/2706409.html
Copyright © 2020-2023  润新知