CR的代码文本

all for learning about the world
  订阅 订阅  :: 管理

【转】C RunTime Library 暨 深入理解编译选项的含义 - 02

Posted on 2011-05-31 16:36  mumuliang  阅读(1753)  评论(0编辑  收藏  举报
以下内容来源于网络,作者不明。

(接上文)

 
四 各种C运行时库的区别
 

编译器链接选项:

 
Visual C++编译时到底哪个C运行时库联入程序取决于编译选项,选项告诉编译器应用程序想使用什么版本的C标准程序库。与标准程序库有关的选项:/ML、/MLd、/MT、/MTd、/MD、/MDd
 
/ML对应单线程静态版的标准程序库(libc.lib);
/MT对应多线程静态版标准库(libcmt.lib),此时编译器会自动定义_MT宏;
/MD对应多线程DLL版(导入库msvcrt.lib,DLL是msvcrt.dll),编译器自动定义_MT和_DLL两个宏。
 
后面加d的选项都会让编译器自动多定义一个_DEBUG宏,表示要使用对应标准库的调试版,因此:
/MLd对应调试版单线程静态标准库(libcd.lib);
/MTd对应调试版多线程静态标准库(libcmtd.lib);
/MDd对应调试版多线程DLL标准库(导入库msvcrtd.lib,DLL是msvcrtd.dll)。
 
VC2005/VC6.0中通过以下方法设置选择哪个C run-time library联入你的程序:
 
VC2005: To find these options in the development environment, click Project on the Project menu, choose Properties… item. Then click the C/C++ tab, and click Code Generation in the Category box. See the Runtime Library drop-down box.
 
VC6.0:To find these options in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation in the Category box. See the Use Run-Time Library drop-down box.
 
各种C运行时库的区别:
(1)静态链接的单线程库
 
静态链接的单线程库只能用于单线程的应用程序,C运行时库的目标代码最终被编译在应用程序的二进制文件中。通过/ML编译选项可以设置Visual C++使用静态链接的单线程库。
 
(2)静态链接的多线程库
 
静态链接的多线程库的目标代码也最终被编译在应用程序的二进制文件中,但是它可以在多线程程序中使用。通过/MT编译选项可以设置Visual C++使用静态链接的单线程库。
 
(3)动态链接的运行时库
 
动态链接的运行时库将所有的C库函数保存在一个单独的动态链接库MSVCRTxx.DLL中,MSVCRTxx.DLL处理了多线程问题。使用/MD编译选项可以设置Visual C++使用动态链接的运行时库。
 
/MLd、 /MTd或/MDd选项使用Debug Runtime Library(调试版本的运行时刻函数库),与/ML、/MT或/MD分别对应。Debug版本的Runtime Library包含了调试信息,并采用了一些保护机制以帮助发现错误,加强了对错误的检测,因此在运行性能方面比不上Release版本。
 
程序运行时,很大一部分时间是在这些运行库里运行。在程序(Release版)被编译时,VC会根据编译选项(单线程、多线程或DLL)自动将相应的运行时库文件(libc.lib、libcmt.lib或Import library msvcrt.lib)链接进来。
 
注:修改编译选项,将/MD或/MDd改为/MT或/MTd,就实现了对VC运行时库的静态链接,在运行时就不再需要VC的dll了。(静态链接将目标代码直接编译在应用程序的二进制文件中,这样运行时就不需要dll了)
 
开始尝试google test单元测试工具(又是MTd/MDd搞的鬼!)附带VC运行库详解
 
今天试了一下google test,环境是VS2008.
 
下载gtest 1.30,分别在debug和release模式下编译gtest-1.3.0msvc下的项目文件。项目目录中debug文件夹下和release文件下分别生成debug版本的gtest静态库(gtestd.lib)和release版本的gtest静态库(gtest.lib).
 
接着新建测试demo项目。建立win32 console项目,在项目属性中设置附加include目录为gtest-1.3.0include, 根据编译环境是debug或release添加对应的附加依赖项gtestd.lib或gtest.lib。设置附加库路径为对应的lib路径。
 
写好测试程序后编译工程,结果出现了很多“无法解析的外部符号”类型的错误。但是lib都已经添加了呀?!
 
错误原因: 编译测试程序时,项目属性/C++/代码生成/选项中,C++的运行库设置与编译gtest库时的运行库设置不同。
 
在编译gtest库时项目设置中运行库设置成了“多线程调试(/MTd)”,而VS2008默认项目设置是“多线程调试 DLL (/MDd)”,导致很多函数符号无法解析。
 
解决:修改运行库设置,运行库必须与生成gtest.lib的运行库设置相同。
 
使用第三方的库容易造成LNK2005错误――重复定义错误,一般是第三方库的链接方式与现工程不一致造成的,如第三方库采用静态链接,而现工程采用动态链接,或者第三方库用单线程,而现工程采用多线程都会引发此错误。