/MT /MD /ML /MTd /MDd /MLd 的区别(C 运行时库)

参考资料:1.http://www.cnblogs.com/cswuyg/archive/2012/02/03/2336424.html

2.http://www.tuicool.com/articles/zAriqe

3.http://www.cppblog.com/aurain/archive/2008/04/23/47911.html

4.http://qimo601.iteye.com/blog/1550348

首先说/MT

/MT是 "multithread, static version ” 意思是多线程静态的版本,定义了它后,编译器把LIBCMT.lib 安置到OBJ文件中,让链接器使用LIBCMT.lib 处理外部符号。

/MD是 "multithread- and DLL-specific version” ,意思是多线程DLL版本,定义了它后,编译器把MSVCRT.lib 安置到OBJ文件中,它连接到DLL的方式是静态链接,实际上工作的库是MSVCR80.DLL。

即:

静态运行时库:LIBCMT.lib
动态运行时库:MSVCRT.lib + MSVCR80.DLL

================================================================

运行时库是程序在运行时所需要的库文件 ,通常运行时库是以 LIB 或 DLL 形式提供的。 C 运行时库诞生于 20 世纪 70 年代,当时的程序世界还很单纯,应用程序都是单线程的,多任务或多线程机制在此时还属于新观念。所以这个时期的 C 运行时库都是单线程的。

随着操作系统多线程技术的发展,最初的 C 运行时库无法满足程序的需求,出现了严重的问题。 C 运行时库使用了多个全局变量(例如 errno )和静态变量,这可能在多线程程序中引起冲突。假设两个线程都同时设置 errno ,其结果是后设置的 errno 会将先前的覆盖,用户得不到正确的错误信息。

因此, Visual C++ 提供了两种版本的 C 运行时库。一个版本供单线程应用程序调用,另一个版本供多线程应用程序调用。多线程运行时库与单线程运行时库有两个重大差别: 
( 1 )类似 errno 的全局变量,每个线程单独设置一个。这样从每个线程中可以获取正确的错误信息。 
( 2 )多线程库中的数据结构以同步机制加以保护。这样可以避免访问时候的冲突。

Visual C++ 提供的多线程运行时库又分为静态链接库和动态链接库两类,而每一类运行时库又可再分为 debug 版和 release 版,因此 Visual C++ 共提供了 6 个运行时库。如下表:

C 运行时库库文件
Single thread(static link) MLlibc.lib
Debug single thread(static link) MLdlibcd.lib
MultiThread(static link) MTlibcmt.lib
Debug multiThread(static link) MTdlibcmtd.lib
MultiThread(dynamic link) MDmsvert.lib
Debug multiThread(dynamic link) MDdmsvertd.lib

2.C 运行时库的作用 
C 运行时库除了给我们提供必要的库函数调用(如 memcpy 、 printf 、 malloc 等)之外,它提供的另一个最重要的功能是为应用程序添加启动函数。 
C 运行时库启动函数的主要功能为进行程序的初始化,对全局变量进行赋初值,加载用户程序的入口函数。 
不采用宽字符集的控制台程序的入口点为 mainCRTStartup(void) 。下面我们以该函数为例来分析运行时库究竟为我们添加了怎样的入口程序。这个函数在 crt0.c 中被定义,下列的代码经过了笔者的整理和简化:

void mainCRTStartup(void) 

int mainret;

_osver = GetVersion(); 
_winminor = (_osver >> 8) & 0x00FF ; 
_winmajor = _osver & 0x00FF ; 
_winver = (_winmajor << 8) + _winminor; 
_osver = (_osver >> 16) & 0x00FFFF ;

_ioinit();

_acmdln = (char *) GetCommandLineA();

_aenvptr = (char *) __crtGetEnvironmentStringsA();

_setargv(); 
_setenvp();

_cinit();

__initenv = _environ; 
mainret = main( __argc, __argv, _environ );

exit( mainret ); 
}

从以上代码可知,运行库在调用用户程序的 main 或 WinMain 函数之前,进行了一些初始化工作。初始化完成后,接着才调用了我们编写的 main 或 WinMain 函数。只有这样,我们的 C 语言运行时库和应用程序才能正常地工作起来。

除了 crt0.c 外, C 运行时库中还包含 wcrt0.c 、 wincrt0.c 、 wwincrt0.c 三个文件用来提供初始化函数。 wcrt0.c 是 crt0.c 的宽字符集版, wincrt0.c 中包含 windows 应用程序的入口函数,而 wwincrt0.c 则是 wincrt0.c 的宽字符集版。

Visual C++ 的运行时库源代码缺省情况下不被安装。如果您想查看其源代码,则需要重装 Visual C++ ,并在重装在时选中安装运行库源代码选项。

3. 各种 C 运行时库的区别 

( 1 )静态链接的单线程库 
静态链接的单线程库只能用于单线程的应用程序 , C 运行时库的目标代码最终被编译在应用程序的二进制文件中。通过 /ML 编译选项可以设置 Visual C++ 使用静态链接的单线程库。

( 2 )静态链接的多线程库 
静态链接的多线程库的目标代码也最终被编译在应用程序的二进制文件中,但是它可以在多线程程序中使用。通过 /MT 编译选项可以设置 Visual C++ 使用静态链接的单线程库。

( 3 )动态链接的运行时库 
动态链接的运行时库将所有的 C 库函数保存在一个单独的动态链接库 MSVCRTxx.DLL 中, MSVCRTxx.DLL 处理了多线程问题。使用 /MD 编译选项可以设置 Visual C++ 使用动态链接的运行时库。

/MDd 、 /MLd 或 /MTd 选项使用 Debug runtime library( 调试版本的运行时刻函数库 ) ,与 /MD 、 /ML 或 /MT 分别对应。 Debug 版本的 Runtime Library 包含了调试信息,并采用了一些保护机制以帮助发现错误,加强了对错误的检测,因此在运行性能方面比不上 Release 版本。

下面看一个未正确使用 C 运行时库的控制台程序 :

#include <stdio.h> 
#include <afx.h> 
int main() 

CFile file; 
CString str("I love you"); 
TRY 

file.Open("file.dat",CFile::modeWrite | CFile::modeCreate); 

CATCH( CFileException, e ) 

#ifdef _DEBUG 
afxDump << "File could not be opened " << e->m_cause << "n"; 
#endif 

END_CATCH

file.Write(str,str.GetLength()); 
file.Close(); 
}

我们在 "rebuild all" 的时候发生了 link 错误:

nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex 
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex 
main.exe : fatal error LNK1120: 2 unresolved externals 
Error executing cl.exe.

发生错误的原因在于 Visual C++ 对控制台程序默认使用单线程的静态链接库,而 MFC 中的 CFile 类已暗藏了多线程。我们只需要在 Visual C++6.0 中依次点选 Project->Settings-> C/C++ 菜单和选项,在 Project Options 里修改编译选项即可。

不过最上面的那个程序在 6.0里面是可以运行的,现象同2003的是一样的。 
***********************************************

从字面上看,运行库是程序在运行时所需要的库文件。通常运行库是以 DLL 形式提供的。 Delphi 和 C++ Builder 的运行库为 .bpl 文件,实际还是一个 DLL 。运行库中一般包括编程时常用的函数,如字符串操作、文件操作、界面等内容。不同的语言所支持的函数通常是不同的,所以使用的库也是完全不同的,这就是为什么有 VB 运行库、 C 运行库、 Delphi 运行库之分的原因。即使都是 C++ 语言,也可能因为提供的函数不同,而使用不同的库。如 VC++ 使用的运行库和 C++ Builder 就完全不同。

如果不使用运行库,每个程序中都会包括很多重复的代码,而使用运行库,可以大大缩小编译后的程序的大小。但另一方面,由于使用了运行库,所以在分发程序时就必须带有这些库,比较麻烦。如果在操作系统中找不到相应的运行库程序就无法运行。为了解决这个矛盾, Windows 总是会带上它自己开发的软件的最新的运行库。象 Windows 2000 以后的版本都包括 Visual Basic 5.0/6.0 的库。 Internet Explorer 总是带有最新的Visual C++ 6.0 的库。 Windows XP 带有 Microsoft .NET 1.0 (用于 VB.NET 和 C# )的库。Visual C++ 、 Delphi 和 C++ Builder 允许用户选择所编译得到的程序是否依赖于运行库。而 VB 、 FoxPro 、 PowerBuilder 、 LabWindows/CVI 和 Matlab 就不允许用户进行这种选择,必须依赖于运行库。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值