最近在开发一个项目,有比较多的dll模块,以前测试时一直没有发现问题,运行的很正常。今天要发布一个新版本了,就用Bounders Check检查了一下。乖乖,很多错误阿!全部都是:
   Allocation Conflict: Attempting to call global_operator_delete on 0x01566E68; pointer was allocated by malloc.
真是奇怪了,看了n多代码,找不出问题所在,并且这个错误是在pair<string,string> 发现的,好像根本就不是我的问题。
又经历了n多回的看。。。。。。。

     最后终于发现问题了。原来我所有dll模块在生成时用的是多线程调试(/MDd), 但是我的exe也就是访问dll的模块是用单线程调试(/MLd)生成的,但是有意思的是我有一个测试程式也是用“单线程调试(/MLd)”生成的,运行时确很正常。
     问题解决了,小结一下:
          (1)所有的模块,包括dll/exe等,都需要统一的“C Run-Time(CRT) library ” !!!!
          (2)BoundersChecker真的很管用,能帮你找出很多问题,甚至是很多你都没有意识/察觉到的问题。
           (3) MSVCR71.DLL(C run-time library (without iostream or standard C++ library) ) 和 MSVCP71.dll(Standard C++ Library) 访在和exe文件的同一目录下时,BounderChecker也会报 “Allocation Conflict: Attempting to call global_operator_delete on 0x01566E68; pointer was allocated by malloc.”这个错误。
                MSVCR71.DLL : C run-time library (without iostream or standard C++ library) 
                MSVCP71.dll    :  Standard C++ Library)



附:

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


 

在Windows下有六种类型CRTLib(C运行库):
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

MT和MD都适用于多线程,其区别是:
MT为静态链接CRT,这样编译出来exe是自包含的,所以会相对大一些,但运行时不用再load CRT库。
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中起作用。

当工程比较大,包含的lib很多,特别当有外部lib(Third party library)存在时,link很容易发生下面这样的错误。
LIBCMTD.lib(chsize.obj) : error LNK2005: __chsize already defined in MSVCRTD.lib(MSVCRTD.dll)
这说明,你的工程使用了不同类型的CRT。这个时候首先一定要坚信这个原则:整个工程用同样的CRT Lib就可以解决问题。然后耐心一一检查每个lib。
如果恰恰某个外部lib用MT,另一个用MD,这个时候就比较痛苦。
    如果有他们源码,就编译一个MT or MD类型的lib,以统一使用一个类型CRT。
    如果没有,那可能只好选择其他的lib。


另有msdn lib关于:
 

请参见 Run-Time Library Reference  

C Run-Time Libraries

 

This topic discusses the various .lib files that comprise the C run-time libraries as well as their associated compiler options and preprocessor directives.

The following libraries contain the C run-time library functions.

C run-time library (without iostream or standard C++ library) Characteristics Option Preprocessor directives
LIBC.LIB Single-threaded, static link /ML  
LIBCMT.LIB Multithreaded, static link /MT _MT
MSVCRT.LIB Multithreaded, dynamic link (import library for MSVCR71.DLL). Be aware that if you use the Standard C++ Library, your program will need MSVCP71.DLL to run. /MD _MT, _DLL
LIBCD.LIB Single-threaded, static link (debug) /MLd _DEBUG
LIBCMTD.LIB Multithreaded, static link (debug) /MTd _DEBUG, _MT
MSVCRTD.LIB Multithreaded, dynamic link (import library for MSVCR71D.DLL) (debug) /MDd _DEBUG, _MT, _DLL

If you link your program from the command line without a compiler option that specifies a C run-time library, the linker will use LIBC.LIB.

To build a debug version of your application, the _DEBUG flag must be defined and the application must be linked with a debug version of one of these libraries. For more information about using the debug versions of the library files, see CRT Debugging Techniques.

This version of Visual C++ is not conformant with the C99 standard.

Standard C++ Library

Note that starting in Visual Studio .NET 2003, Visual C++ will no longer ship the old iostream libraries. For details, see Upgrade to the Standard C++ Library and the Standard C++ Library Overview.

The new iostream functions, as well as many other new functions, exist in the Standard C++ Library:

Standard C++ Library Characteristics Option Preprocessor directives
LIBCP.LIB Single-threaded, static link /ML  
LIBCPMT.LIB Multithreaded, static link /MT _MT
MSVCPRT.LIB Multithreaded, dynamic link (import library for MSVCP71.dll) /MD _MT, _DLL
LIBCPD.LIB Single-threaded, static link /MLd _DEBUG
LIBCPMTD.LIB Multithreaded, static link /MTd _DEBUG, _MT
MSVCPRTD.LIB Multithreaded, dynamic link (import library for MSVCP71D.DLL) /MDd _DEBUG, _MT, _DLL

When you build a release version of your project, one of the basic C run-time libraries (LIBC.LIB, LIBCMT.LIB, and MSVCRT.LIB) is linked by default, depending on the compiler option you choose (single-threaded, multithreaded, or DLL). If you include a Standard C++ Library header in your code, a Standard C++ Library will be linked in automatically by Visual C++ at compile time. For example:

#include <ios> 

What is the difference between msvcrt.dll and msvcr71.dll?

The msvcrt.dll is now a "known DLL," meaning that it is a system component owned and built by Windows. It is intended for future use only by system-level components. An application should use and redistribute msvcr71.dll, and it should avoid placing a copy or using an existing copy of msvcr71.dll in the system directory. Instead, the application should keep a copy of msvcr71.dll in its application directory with the program executable. Any application built with Visual C++ .NET using the /MD switch will necessarily use msvcr71.dll.

What problems exist if an application uses both msvcrt.dll and msvcr71.dll?

If you have a .lib or .obj file that needs to link to msvcrt.lib, then you should not have to recompile it to work with the new msvcrt.lib in Visual C++ .NET. The .lib or .obj file may rely on the sizes, field offsets, or member function names of various CRT classes or variables, and those should all still exist in a compatible way. When you relink against msvcrt.lib, your final EXE and DLL image will now have a dependency on msvcr71.dll instead of msvcrt.dll.

If you have more than one DLL or EXE, then you may have more than one CRT, whether or not you are using different versions of Visual C++. For example, statically linking the CRT into multiple DLLs can present the same problem. Developers encountering this problem with static CRTs have been instructed to compile with /MD to use the CRT DLL. Now that the CRT DLL has been renamed to msvcr71.dll, applications may have some components linked to msvcrt.dll and others to msvcr71.dll. If your DLLs pass CRT resources across the msvcrt.dll and msvcr71.dll boundary, you will encounter issues with mismatched CRTs and need to recompile your project with Visual C++ .NET.

See Also

Run-Time Library Reference

posted on 2008-02-04 13:05  Frodo  阅读(4814)  评论(4编辑  收藏  举报