做开发差不多一年多了,突然感觉对VC的工程设置都不是很清楚,天天要和VC见面,虽然通常情况下一般都不会修改工程设置,但是还是有必要对它的一些设置项的来龙去脉有一定的了解,所以狂查资料,稍作整理,总结一篇文档,方便以后查阅,总得记录点什么,温故而知新嘛。
进入工程设置界面有两种方法:
方法一,选择法:【Project】->【Settings】
方法二,快捷键:【Alt+F7】
打开工程设置对话框,如下图:
左边的列表可以选择要设置的工程编译方式(Debug或Release),如果多个工程,还可以选择要设置的工程。右边是一个属性页,内容十分丰富,依次是:General , Debug , C/C++ , Link , Resource , MIDL , Browse Info , Custom Build , Pre-link Step , Post-build step
下面主要介绍各个选项的功能:
一、【General】
设置工程的一般特性。
1.Microsoft Foundation Classes 连接MFC静态库的方式,默认为共享的DLL方式,对一些不支持MFC42的机器环境来说,选择静态编译还是有必要的。
2.Intermediate files 中间文件输出路径,比如:*.obj、*.pch、*.res、*.sbr、*.idb、*.pdb
3.Output files 输出文件路径,比如:*.exe。
4.Allow per-configuration dependencies 按外部制作文件(exported makefile)方式为每个工程配置导出不同的可建立项目。
二、【Debug】
设置工程调试的选项。
Category 选项种类,先看看General种类选项卡
1.Executable for debug session 如果是dll的工程,需要指定启动它的exe文件路径,如果是exe工程,默认当前工程路径。
2.Work directory 设置调试程序的工作路径,默认exe当前路径,也可以为空。
3.Program arguments 程序启动命令行参数,作控制台程序的时候经常要用,可以传递参数给main函数。
4.Remote executable path and file name远程可执行文件的路径和文件名,一般都用不上,忽略好了,设置为空。
Category中Additional DLLS种类选项卡
选择,出现如下对话框:
1.Modules 如果你需要调试的DLL是动态装入(LoadLibrary)的,则需要在Additional DLLs中添加这个DLL文件。修改Additional DLLs后不需要重新编译就能起效果,预加载DLL和编译代码本身没联系。
三、【C/C++】
这一页内容很多,选择项通过 Category 来设置。
General种类选项卡
选择,如下图所示:
1.Warninig level 警告级别,VC默认为3,一般不更改,等级越低,对代码的要求就越严格。
2.Optimizations Optimizations优化级别,Debug下默认设置为Disable(Debug),就是不优化,在Release下默认设置为Maximize Speed,就是最大速度优化。在追求效率或者编译结果的时候可以选择最大速度或最小尺寸的选项,不过微软不保证优化的准确性。
4.Waring as error 不用多说了,经常忽略警告的人不会选这项吧。最好别选,否则你会烦死。
5.Generate browse info 用以生成.sbr文件,记录类、变量等符号信息,可以在Category的Listing Files项中进行更多的设置。产生浏览信息,在编辑调试加了一些功能,会产生很大的编译文件,建议不要选
6.Debug info 生成调试信息,选择调试信息的详细程度,在debug情况下,一般选择Program DataBase 或 Program DataBase for Editon and continue 二者区别在于后者可以在调试过程中,修改代码后,部分编译后,在当前环境继续执行,虽然功能很强,建议还是用前者吧。Release一般选择None。
None,不产生任何调试信息(编译比较快);
Line Numbers Only,仅生成全局的和外部符号的调试信息到.OBJ文件或.EXE文件,减小目标文件的尺寸;
C 7.0- Compatible,记录调试器用到的所有符号信息到.OBJ文件和.EXE文件;
Program Database,创建*.pdb文件记录所有调试信息;
Program Database for Edit and Continue,创建*.pdb文件记录所有调试信息,并且支持调试时编辑。
7.Preprocessor definitions 预定义宏,Defines a preprocessing symbol for your source file,相当于全局【#define】。提示:一般定义了UNICODE _UNICODE则认为是使用unicode编码,没定义则认为是MBCS。
C++ Language种类选项卡
1.pointer_to_member representation用来设置类定义/引用的先后关系,一般为Best-Case Always表示在引用类之前该类肯定已经定义了。
2.Enable Exception Handling,进行同步的异常处理;
3.Enable Run-Time Type Information,迫使编译器增加代码在运行时进行对象类型检查;
4.Disable Construction Displacements,设置类构造/析构函数调用虚函数问题。
Code Generation种类选项卡
定义代码产生的规则。
1.Processor 表示代码指令优化,可以为80386、80486、Pentium、Pentium Pro,或者Blend表示混合以上各种优化。
2.Use run-time library用以指定程序运行时使用的运行时库(单线程或多线程,Debug版本或Release版本),有一个原则就是,一个进程不要同时使用几个版本的运行时库。
Single-Threaded,静态连接LIBC.LIB库;
Debug Single-Threaded,静态连接LIBCD.LIB库;
Multithreaded,静态连接LIBCMT.LIB库;
Debug Multithreaded,静态连接LIBCMTD.LIB库;
Multithreaded DLL,动态连接MSVCRT.DLL库;
Debug Multithreaded DLL,动态连接MSVCRTD.DLL库。
连接了单线程库就不支持多线程调用,连接了多线程库就要求创建多线程的应用程序。
3.Calling convention 可以用来设定调用约定,有三种:__cdecl、__fastcall和__stdcall。各种调用约定的主要区别在于,函数调用时,函数的参数是从左到右压入堆栈还是从右到左压入堆栈;在函数返回时,由函数的调用者来清理压入堆栈的参数还是由函数本身来清理;以及在编译时对函数名进行的命名修饰(可以通过Listing Files看到各种命名修饰方式)。
4.Struct member alignment 用以指定数据结构中的成员变量在内存中是按几字节对齐的,根据计算机数据总线的位数,不同的对齐方式存取数据的速度不一样。这个参数对数据包网络传输等应用尤为重要,不是存取速度问题,而是数据位的精确定义问题,一般在程序中使用#pragma pack来指定。
Customize种类选项卡
1.Disable language extensions 禁止语言扩展(Microsoft Extensions to C),表示不使用微软为标准C做的语言扩展。
2.Eliminate Duplicate Strings 主要用于字符串优化(将字符串放到缓充池里以节省空间),使用这个参数,使得
char *sBuffer = "This is a character buffer";
char *tBuffer = "This is a character buffer";
sBuffer和tBuffer指向的是同一块内存空间;
3.Enable Function-Level Linking 告诉编译器将各个函数按打包格式编译;
4.Enables minimal rebuild,通过保存关联信息到.IDB文件,使编译器只对最新类定义改动过的源文件进行重编译,提高编译速度;
5.Enable Incremental Compilation,同样通过.IDB文件保存的信息,只重编译最新改动过的函数;
6.Suppress Startup Banner and Information Messages 设置预编译文件(pch)的存放路径及(或)文件名,在Project Options中配置。用以控制参数是否在output窗口输出。
Listing Files种类选项卡
1.Generate browse info 功能上面已经提到过,这里可以进行更多的设置。
2.Exclude Local Variables from Browse Info表示是否将局部变量的信息放到*.sbr文件中。
3.Listing file type 可以设置生成的列表信息文件的内容:
Assembly-Only Listing,仅生成汇编代码文件(.asm扩展名);
Assembly With Machine Code 生成机器代码和汇编代码文件(.cod扩展名);
Assembly With Source Code生成源代码和汇编代码文件(.asm扩展名);
Assembly, Machine Code,and Source,生成机器码、源代码和汇编代码文件(.cod扩展名)。
Listing file name为生成的信息文件的路径,一般为Debug或Release目录下,生成的文件名自动取源文件的文件名。
Optimizations种类选项卡
1.Optimizations 代码优化设置。可以选择Maximize Speed生成最快速的代码,或Minimize Size生成最小尺寸的程序,或者Customize定制优化。定制的内容包括:
Assume No Aliasing,不使用别名(提高速度);
Assume Aliasing Across Function Calls,仅函数内部不使用别名;
Global Optimizations,全局优化,比如经常用到的变量使用寄存器保存,或者循环内的计算优化,如:
i = -100;
while ( i < 0 ){ i += x + y;}
会被优化为
i = -100;
t = x + y;
while( i < 0 ){i += t;}
Generate Intrinsic Functions,使用内部函数替换一些函数调用(提高速度);
Improve Float Consistency,浮点运算方面的优化;
Favor Small Code,程序(exe或dll)尺寸优化优先于代码速度优化;
Favor Fast Code,程序(exe或dll)代码速度优化优先于尺寸优化;
Frame-Pointer Omission,不使用帧指针,以提高函数调用速度;
Full Optimization,组合了几种参数,以生成最快的程序代码。
2.Inline function expansion 内联函数扩展的三种优化(使用内联可以节省函数调用的开销,加快程序速度):
Disable,不使用内联;
Only __inline,仅函数定义前有inline或__inline标记使用内联;
Any Suitable,除了inline或__inline标记的函数外,编译器“觉得”应该使用内联的函数,都使用内联。
Precompiled Headers种类选项卡
预编译头文件的设置。使用预编译可以提高重复编译的速度。VC一般将一些公共的、不大变动的头文件(比如afxwin.h等)集中放到stdafx.h中,这一部分代码就不必每次都重新编译(除非是Rebuild All)。
Preprocessor种类选项卡
预编译处理。可以定义/解除定义一些常量。
Additional include directories,可以指定额外的包含目录,一般是相对于本项目的目录,如..Include。
四、【Link】
设置连接的选项,可以设置生成的文件路径、文件名;连接的库文件。
Genaral种类选项卡
设置界面如下图所示:
1.Output file name 输出文件名称,支持相对路径
2.Object/library module 工程所需要的lib,默认当前路径
3.Generate debug info 产生debug信息。生成Debug信息到*.pdb文件(具体格式可以在Category->Debug中设置),Debug默认为true,Release默认为false
4.Ignore All Default Libraries 放弃所有默认的库连接
5.Link incrementally 增量连接,必须选择Program database选项,提高编译连接的速度,通过生成. ILK文件实现递增式连接以提高后续连接速度,但一般这种方式下生成的文件(EXE或DLL)较大
6.Generate Mapfile 生成*.map文件记录模块相关信息
7.Enable profiling 允许程序以profiling启动,可以测试程序的效率等
Customize种类选项卡
这里可以进行使用程序数据库文件的设置。
1.Use program database允许使用程序数据库,这样连接器会把调试信息放在程序数据库中,如果不选中该选项,那么也不能使用递增连接方式
2.Force File Output 强制产生输出文件(EXE或DLL), 即使某个模块引用了一些未定义或者重复定义的符号,连接器仍然会强制(但不一定能正确运行)产生输出文件(EXE或DLL)
3.Print Progress Messages 可以将连接过程中的进度信息输出到Output窗口
Debug种类选项卡
设置是否生成调试信息,以及调试信息的格式。格式可以有Microsoft Format、COFF Format(Common Object File Format)和Both Formats三种选择;Separate Types,表示将Debug格式信息以独立的*.pdb文件存放,还是直接放在各个源文件的*.pdb文件中。选中的话,表示采用后者的方式,这种方式调试启动比较快。
Input种类选项卡
这里可以指定要连接的库文件,放弃连接的库文件。还可以增加额外的库文件目录,一般是相对于本项目的目录,如..\Lib。
Force Symbol References,可以指定连接特定符号定义的库。
Output种类选项卡
1.Base Address 可以改变程序默认的基地址(EXE文件默认为0x400000,DLL默认为0x10000000),操作系统装载一个程序时总是试着先从这个基地址开始
2.Entry-Point Symbol 可以指定程序的入口地址,一般为一个函数名(且必须采用__stdcall调用约定)。一般Win32的程序,EXE的入口为WinMain,DLL的入口为DllEntryPoint;最好让连接器自动设置程序的入口点。默认情况下,通过一个C的运行时库函数来实现:控制台程序采用mainCRTStartup (或wmainCRTStartup)去调用程序的main (或wmain)函数;Windows程序采用WinMainCRTStartup (或 wWinMainCRTStartup)调用程序的WinMain (或 wWinMain,必须采用__stdcall调用约定);DLL采用_DllMainCRTStartup调用DllMain函数(必须采用__stdcall调用约定)
3.Stack allocations 用以设置程序使用的堆栈大小(请使用十进制),默认为1兆字节。
4.Version Information 告诉连接器在EXE或DLL文件的开始部分放上版本号
值得注意的是,上面各个参数是大小写敏感的;在参数后加上“-”表示该参数无效;各个参数值选项,有“*”的表示为该参数的默认值;可以使用页右上角的“Reset”按钮来恢复该页的所有默认设置。
五、【Browse Info】
在这个选项卡中,我们可以指定是否在建立工程的同时也生成浏览信息文件,有了这个文件后,我们就能够在文本编辑器中通过关联菜单的相应命令快速定位到某个符号的定义或引用的地方。
六、【Pre-link Step】
连接前的步骤,可以在工程连接前,完成一些工作,方式以dos命令行执行,通常拷贝lib。
七、【Post-build step】
这个选项卡用于添加在工程建立完毕之后要执行的命令 如 “copy debug\TestDll.lib C:\bin\TestDll.lib” 并在C盘下建一个bin目录做的事情就是把TestDLL.lib拷贝到C:\bin所在的文件夹中。
工程设置实例
一.C++ 调用*.lib的方法:
1.隐式的加载时链接,有三种方法:
a.LIB文件直接加入到工程文件列表中:
在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中"Add Files to Project"菜单,在弹出的文件对话框中选中要加入DLL的LIB文件。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
b.设置工程的 Project Settings来加载DLL的LIB文件:
打开工程的 Project Settings菜单,选中Link,然后在Object/library modules下的文本框中输入DLL的LIB文件,如you.lib(或者lib文件的路径,包括文件名)。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
c.通过程序代码的方式
加入预编译指令#pragma comment (lib, "*.lib"),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。因为,在Debug方式下,产生的LIB文件是Debug版本,如Regd.lib;在Release方式下,产生的LIB文件是Release版本,如Regr.lib。然后在首先要使用该函数的地方加上该LIB的头文件,如#include "..\lib.h"即可(没有头文件当然就不用了)。
当应用程序对DLL的LIB文件加载后,还需要把DLL对应的头文件(*.h)包含到其中,在这个头文件中给出了DLL中定义的函数原型,然后声明。
2.显式的运行时链接
隐式链接虽然实现较简单,但除了必须的*.dll文件外还需要DLL的*.h文件和*.lib文件,在那些只提供*.dll文件的场合就无法使用,而只能采用显式链接的方式。这种方式通过调用API函数来完成对DLL的加载与卸载,能更加有效地使用内存,在编写大型应用程序时往往采用此方式。这种方法编程具体实现步骤如下:
使用Windows API函数Load Library或者MFC提供的AfxLoadLibrary将DLL模块映像到进程的内存空间,对DLL模块进行动态加载。
使用GetProcAddress函数得到要调用DLL中的函数的指针。
不用DLL时,用Free Library函数或者AfxFreeLibrary函数从进程的地址空间显式卸载DLL。
动态装载*.dll,未加路径,将在三个默认路径中寻找
(1) windows的系统目录:\windows\system;
(2) dos中path所指出的任何目录;
(3) 程序所在的目录;
二:如何在Release状态下进行调试
1.选择Project -> Setting -> Project Setting对话框
2.选择Release状态
3.C/C++标签中的Category选General,Optimizations选Disable(Debug),Debut info选Program Database
4.在Link标签中选中Generate debug info复选框。
注:只是一个介乎Debug合Release的中间状态,所有的ASSERT、VERIFY都不起作用,函数调用方式已经是真正的调用,而不查表,但是这种状态下QuickWatch、调用队列跟踪功能仍然有效,和Debug版一样。
小知识:
1.Release和Debug有什么不同
Release版称为发行版,Debug版称为调试版。
Debug中可以单步执行、跟踪等功能,但生成的可执行文件比较大,代码运行速度较慢。Release版运行速度较快,可执行文件较小,但在其编译条件小无法执行调试功能。
Release的exe文件链接的是标准的MFC DLL(Use MFC in a shared or static dll),比如MFC42.DLL。这些DLL在安装Windows的时候,已经配置,所以这些程序能够在没有安装Visual C++ 6.0的机器上运行。而Debug版本的exe链接了调试版本的MFC DLL文件,如MFC42D.DLL。在没有安装Visual C++6.0的机器上不能运行,因为缺MFC42D.DLL等,除非选择use static dll when link。
2.ASSERT和VERIFY有什么区别
ASSERT里面的内容在Release版本中不编译,VERIFY里面的内容仍然翻译,但不再判断真假。所以后者更安全一点。
例如ASSERT(file.Open(strFileName))。
一旦到了Release版本中,这一行就忽略了,file根本就不Open()了,而且没有任何出错的信息。如果用VERIFY()就不会有这个问题。
3.Workspace和Project之间是什么样的关系
每个Workspace可以包括几个project,但只有一个处于Active状态,各个project之间可以有依赖关系,在project的Setting..中可以设定,比如那个Active状态的project可以依赖于其他的提供其函数调用的静态库。
4.如何在非MFC程序中使用ClassWizard
在工程目录下新建一个空的.RC文件,然后加入到工程中就可以了。
5.在编辑状态下发现成员变量或函数不能显示提示是如何打开显示功能
这似乎是目前这个Visual C++ 6.0版本的一个bug,可按如下步骤使其正常,如再出现,可如法炮制:
(1) 关闭Project
(2) 删除“工程名.ncb”文件
(3) 重新打开工程
6.如何将一个通过ClassWizard生成的类彻底删除
首先在工作区的FileView中选中该类的.h和.cpp文件,按delete删除,然后在文件管理器中将这两个文件删除,再运行ClassWizard,这时出现是否移走该类的提示,选择remove就可以了。
7.如何将再workspace中消失的类找出来
打开该类对应的头文件,然后将其类名随便改一下,这个时候工作区就会出现新的类,再将这个类改回原来的名字就可以了。
8.如何添加Lib文件到当前工程
单击菜单【Project】->【Settings…】弹出“Project Setting”对话框,切换到“Link”标签页,在“Object/library modules”处输入Lib文件名称,不同的Lib之间用空格格开。
9.如何快速删除项目下的Debug文件夹中临时文件
在工作区的FileView视图中选中对应的项目,单击右键弹出菜单,选择【Clean(selection only)】菜单即可
10.如何快速生成一个现有工程除了工程名外完全相同的新工程。
在新建工程的“New”对话框中选择“Custom Appwizard”项,输入新工程的名字,单击【OK】按钮。出现“Custom AppWizard”项,输入新工程的名字,单击【OK】按钮。出现“Custom AppWizard-Step 1 of 2”对话框,选择“An existing Project”项,单击【Next】按钮。出现“Custom AppWizard-Step 2 of 2”对话框,选择现有工程的工程文件名,最后单击【Finish】按钮。编译后就生成一个与现有工程相同但可以重新取名的工程AppWizard。
现在就可以项用MFC AppWizard一样用这个定制的向导。如果不想用了,可以在Visual C++ 6.0安装目录下Common\MSDev98\Template目录中删除该Wizard对应的.awx和.pdb文件。
11. 如何解决Visual C++ 6.0不正确连接的问题
情景:明明之间改动了一个文件,却要把整个项目全部重新编译链接一次。刚刚链接好,一运行,有提示重新编译链接一次。
这是因为出现了未来文件(修改时间和创建时间比系统时间晚)的缘故。可以这样处理:找到工程文件夹下的debug目录,将创建和修改时间都比系统时间晚的文件全部删除,然后再从新“Rebuild All”一次。
12.Visual C++ 6.0工程中的项目文件都表示什么。
.opt:工程关于开发化境的参数文件。如工具条位置等信息。
.aps(AppStudio File)资源辅助文件,二进制格式,一般不用去管他。
.clw:ClassWizard信息文件,实际上是INI文件格式,又兴趣可以研究一下。有时候ClassWizard出了问题,手工修改CLW文件可以解决。如果此文件不存在的话,每次用ClassWizard的时候回提示是否重建。
.dsp(DevelopStudio Project):项目文件,文本格式,不过不熟悉的或不要手工修改。
.dsw(DevelopStudio Workspace):是工作区文件,其他特点和.dsp差不多。
.plg:是编译信息文件,编译时的error和warning信息文件(实际上时一个html文件),一般用处不大。在单击菜单【Tool】->【Option】弹出的对话框里面有个选项可以控制这个文件的生成。
.hpj(Help Project):是生成帮助文件的工程,用microsoft Help Compiler可以处理。
.mdp(Microsoft DevStudio Project):是旧版本的项目文件,如果要打开此文件的话,回提示你是否转换成新的.dsp格式。
.bsc:是用于浏览项目信息的,如果用Source Brower的话就必须又这个文件。如果不用这个功能的话,可以在Project Options里面去掉Generate Browse Info File,这样可以加快编译速度。
.map是执行文件的影像信息记录文件,除非对系统底层,这个文件一般用不着。
.pch(Pre-Compiled File):是与编译文件,可以加快编译速度,但是文件非常大。
.pdb(Program Database/C:在预处理输出中保留注释语句):记录了程序有关的一些数据和调试信息,在调试的时候可能有用。
.exp:只有在编译DLL的时候才会生成,记录了DLL文件的一些信息,一般也没有用。
.ncb:无编译浏览文件(no compile browser)。当自动完成功能出问题时可以删除此文件。编译工程后回自动生成。
13. 完全可以删掉以下文件:.dsw、.ncb、.opt、.aps、.clw、. plg文件以及Debug、Release目录下的所有文件。
14. 如何给已有的Project改名字?将该Project关掉。然后以文本格式打开.dsp文件,替换原来的Project名字即可。
15.VC6对类成员的智能提示功能很有用,但有时候会失灵。你可以先关掉项目,将.clw和.ncb删掉,然后重新打开项目,点击菜单项View->ClassWizard,在弹出的对话框中按一下“Add All”按钮;重新Rebuild All。应该可以解决问题。