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 |
|
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
|