VS的编译选项
转载下,对于VS的编译选项介绍蛮清楚的!!
1. 静态链接库、动态链接库、CRT、STL
我们要到一个函数,要么是需要该函数的源代码,要么是知道该函数的声明并有该函数的实现,这里的“实现”又分为静态链接库、动态链接库。在windows平台上,静态链接库对应以.lib为后缀的库文件,动态链接库对应.dll为后缀的动态链接库文件。关于静态链接库、动态链接库请参考wikipedia相应条目:
http://en.wikipedia.org/wiki/Static_library
http://en.wikipedia.org/wiki/Dynamic-link_library
我们用VC++写的程序默认编译为可执行文件(.exe),如果想发布自己的库,可以在VS的“项目属性 >> 配置属性 >> 常规 >> 配置类型”修改。这样如果以后想用这些函数就不需要引入对应.cpp文件,而只需包含带有该函数声明的头文件,并引用库文件即可——对于静态链接库,可以用“#pragma comment (lib, "xxx.lib")”指令,或在VS的“项目属性 >> 配置属性 >> 链接器 >> 输入 >> 附加依赖”中添加;对于动态链接库,可以用“__declspec(dllimport)”声明要用的函数,如果为.dll文件实现了导入库(对应的.lib文件,里面实现了函数导入,使用同静态链接库),则动态库的使用同静态库,只是程序执行时需要.dll文件。msdn上有静态库和动态库的使用教程:
http://msdn.microsoft.com/en-us/library/ms235627.aspx
http://msdn.microsoft.com/en-us/library/ms235636.aspx
简单总结,可执行文件(.exe)和库文件(.lib、.dll)都含有源代码编译出来的可执行二进制代码。静态链接和动态链接的区别在于:静态链接编译出的可执行代码体积较大,动态链接编译出的可执行代码执行时依赖对应的.dll文件。
CRT(C语言运行库)实现了C语言相关初始化代码以及实现了C函数库,C++可以看做C语言的超集,所以C++并没有“CPRT(C++运行库)”,C++也使用CRT,标准C++除CRT外还实现了STL(standard
C++ library,C++标准库,注意STL是Standard Template
Library的缩写,因为C++标准库主要是用模板实现的)。既然函数的“实现”至少有静态和动态之分,那CRT或STL也有不止一个版本,后文针对VC2010平台讨论这些版本。
总结,CRT是C语言函数库及初始化代码的实现,STL是C++标准库的实现,所谓“实现”就是由源代码编译出来的.lib、.dll文件等。
2. VS的编译选项
在VC2010上,CRT和STL至少分为静态和动态,静态和动态中又各自有Debug和Release版本(早期VC还有单线程和多线程之分,目前VC++中只提供多线程版本),这样CRT和STL都有至少四个版本。现在来解释引言中的符号未定义、符号重定义链接错误的可能情景,程序A中调用了函数f,函数f是在程序B中编写的,为了使用f,将程序B编译为库(而非.exe)——静态库:B.lib\动态库:B.lib、B.dll,程序A为了使用f,包含头文件B.h(其中有函数f的声明)并引用B.lib:
1 #include"B.h"
2 #pragma comment (lib, "B.lib")
如果没有上面的第二句代码,则出现了符号未定义的链接错误:
main.obj : error LNK2019: 无法解析的外部符号 _f@0,该符号在函数 _main 中被引用
上面错误信息中的“_f@0”具体取决于函数调用约定的命名方式(_cdecl、_stdcall等)。
如果编译程序B时使用了动态版本的CRT而编译A时使用的是静态版本CRT(即A、B使用了不同版本的CRT),则出现了符号重定义之类的链接错误(不绝对)。
当然如果用动态链接版本的B,程序A运行时可执行文件搜索路径中必须包含B.dll,否则报告“丢失xxx.dll”之类的错误。
设置程序到底使用哪个版本的CRT可在VS的“项目属性 >> 配置属性 >> C/C++ >> 代码生成 >> 运行库”中设置,现在将几种设置对应的库文件,编译器的宏定义列在下表:
Option |
Preprocessor directives |
C run-time library (without iostream or standard C++ library) |
Standard C++ Library |
/MT |
_MT |
libcmt.lib |
LIBCPMT.LIB |
/MD |
_MT, _DLL |
msvcrt.lib (import library for MSVCR100.DLL) |
MSVCPRT.LIB (import library for MSVCP100.dll) |
/MTd |
_DEBUG, _MT |
libcmtd.lib |
LIBCPMTD.LIB |
/MDd |
_DEBUG, _MT, _DLL |
msvcrtd.lib (import library for MSVCR100D.DLL) |
MSVCPRTD.LIB (import library for MSVCP100D.DLL) |
其中,MT为是multi-thread的缩写,上面说了,所有这些库都是多线程的,大写D代表DLL,小写d代表debug,如/MDd下引用动态链接调试版本的库,并且编译器定义宏_DEBUG, _MT, _DLL(程序中可以用#ifdef指令来判断库版本),引用的CRT实现文件为MSVCPRTD.LIB,该文件只是导入库并没有具体的执行二进制代码,程序运行时动态链接MSVCP100D.DLL文件,STL实现文件同理。
文件名“MSVC[R,P]100[D]”中的“100”对应VC2010,VC2003、VC2005、VC2008、VC2010、VC2012分别为71、80、90、100、110,有些时候我们运行一个程序提示“丢失msvcrxxx.dll”,可以通过安装对应VS来解决,如果不想安装VS,也可通过安装“Microsoft Visual C++ 20xx [SP1] Redistributable Package”来解决。
可参考msdn的C run-time libraries条目:
http://msdn.microsoft.com/en-us/library/vstudio/abx4dbyh(v=vs.100).aspx
转载自: http://www.cnblogs.com/liangliangh/p/3521381.html
VS的编译选项的更多相关文章
- 使用--gc-section编译选项减小程序体积
本周在给程序添加功能的时候,突然发现,我只是写了几个函数,还没调用,size就变大了.这肯定是不行的嘛,没用的函数就应该不链接进来,占用我宝贵的空间. 这种功能,讲道理编译器肯定要支持的,于是搜了一下 ...
- 2015-08-26: GCC编译选项(转载)
gcc提供了大量的警告选项,对代码中可能存在的问题提出警告,通常可以使用-Wall来开启以下警告: -Waddress -Warray-bounds (only with -O2) ...
- VS 的编译选项 build下的 platform target -- Any CPU和x86有什么影响?
VS 的编译选项 build下的platform -- Any CPU和x86有什么影响? 现在的问题是,我的一个assembly用Any CPU编译就不能在64位系统下运行了,但是用x86编译就ok ...
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
一.MD(d).MT(d)编译选项的区别 1.编译选项的位置 以VS2005为例,这样子打开: 1) 打开项目的Property Pages对话框 2) 点击左侧C/C ...
- MD(d)、MT(d)编译选项的区别
1.编译选项的位置 以VS2005为例,这样子打开: 1) 打开项目的Property Pages对话框 2) 点击左侧C/C++节 3) 点击Code ...
- Android编译选项eng、user、userdebug的区别
eng:debug 版本 user: release 版本 userDebug版本:部分debug版本 LOCAL_MODULE_TAGS := user eng optional test这个样子. ...
- Makefile编译选项CC与CXX/CPPFLAGS、CFLAGS与CXXFLAGS/LDFLAGS
转自:http://www.firekyrin.com/archives/597.html 编译选项 让我们先看看 Makefile 规则中的编译命令通常是怎么写的. 大多数软件包遵守如下约定俗成的规 ...
- Xcode 常用编译选项设置
Xcode 常用编译选项设置 在xcconfig文件中指定即可. 用标准库连接 LINK_WITH_STANDARD_LIBRARIES = YES如果激活此设置,那么编译器在链接过程中会自动使用通过 ...
- gcc常用的编译选项
一.程序编译过程 程序编译的时候,要分四个阶段 : 1.预处理阶段,完成宏定义和include文件展开等工作: 2.根据编译参数进行不同程度的优化,编译成汇编代码: 3.用汇编器把汇编代码进一步生成目 ...
- GCC编译选项
一.看例子分析gcc 的编译选项 gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld 1.-I /home/h ...
随机推荐
- [1-5] 把时间当做朋友(李笑来)Chapter 5 【小心所谓成功学】 摘录
有一个事实非常简单,却令人难以接受.这世界上所有的资源并非平均分布在每一个人的身上,能够比较接近地表示这种分布情况的数学曲线叫做“正态分布曲线”(Normal Distribution Curve) ...
- MySQL学习总结(五)表数据查询
查询数据记录,是指从数据库对象表中获取所要查询的数据记录,该操作可以说是数据最基本的操作之一,也是使用频率最高.最重要的数据操作. 1.单表数据记录查询 1.1.简单数据查询 SELECT field ...
- 深入分析JavaWeb Item22 -- 国际化(i18n)
一.国际化开发概述 软件的国际化:软件开发时,要使它能同一时候应对世界不同地区和国家的訪问,并针对不同地区和国家的訪问.提供对应的.符合来訪者阅读习惯的页面或数据. 国际化(international ...
- YII用户注冊表单的实现熟悉前台各个表单元素操作方式
模还是必须定义两个基本方法.还有部分label标签映射为汉字,假设进行表单验证,还要定义一些验证规则: <? php /* * 用户模型 * */ class user extends CAct ...
- php中的匿名函数的注意事项
在php5.3以后,php加入匿名函数的使用,今天在使用匿名的时候出现错误,不能想php函数那样声明和使用,详细看代码 $callback=function(){ return "aa&qu ...
- C语言基础(19)-结构体,联合体,枚举和typedef
一.结构体 1.1 结构体struct定义及初始化 #include <stdio.h> // 这个头文件在系统目录下 #include <stdlib.h> // 使用了sy ...
- C++程序设计(第4版)读书笔记_指针、数组与引用
void * 函数指针和指向类成员的指针不能被赋给void * 字符串字面值常量 #include <iostream> using namespace std; void f() { c ...
- 如何在Linux下统计高速网络中的流量
参考: http://www.geekfan.net/5558/ http://blog.jobbole.com/23638/ http://www.csdn.net/article/2014-03- ...
- Jenkins安装和配置系列
转自:http://www.cnblogs.com/zz0412/tag/jenkins/default.html?page=1 Jenkins进阶系列之——18Jenkins语言本地化 Jen ...
- Vue 组件6内联模板
如果子组件有inline-template特性,组件将把它的内容当做模板,而不是把它当做分发内容,这样模板更灵活. <my-component inline-template> <d ...