VC中编译、运行程序的小知识点

http://topic.csdn.net/t/20050428/22/3974737.html

 1、Run-Time   Library 
Run-Time   Library是编译器提供的标准库,提供一些基本的库函数和系统调用。 
我们一般使用的Run-Time   Library是C   Run-Time   Libraries。当然也有Standard   C++   libraries。   
C   Run-Time   Libraries实现ANSI   C的标准库。VC安装目录的CRT目录有C   Run-Time库的大部分源代码。   
C   Run-Time   Libraries有静态库版本,也有动态链接库版本;有单线程版本,也有多线程版本;还有调试和非调试版本。 
可以在 "project "- "settings "- "C/C++ "- "Code   Generation "中选择Run-Time   Library的版本。 

动态链接库版本: 
/MD   Multithreaded   DLL   使用导入库MSVCRT.LIB 
/MDd   Debug   Multithreaded   DLL   使用导入库MSVCRTD.LIB 

静态库版本: 
/ML   Single-Threaded   使用静态库LIBC.LIB   
/MLd   Debug   Single-Threaded   使用静态库LIBCD.LIB 
/MT   Multithreaded   使用静态库LIBCMT.LIB 
/MTd   Debug   Multithreaded   使用静态库LIBCMTD.LIB 

C   Run-Time   Library的标准io部分与操作系统的关系很密切,在Windows上,CRT的io部分代码只是一个包装,底层要用到操作系统内核kernel32.dll中的函数,在编译时使用导入库kernel32.lib。这也就是为什么在嵌入式环境中,我们一般不能直接使用C标准库。 
在Linux环境当然也有C标准库,例如: 
ld   -o   output   /lib/crt0.o   hello.o   -lc 
参数 "-lc "就是在引用C标准库libc.a。猜一猜 "-lm "引用哪个库文件? 

2、常见的编译参数 
VC建立项目时总会定义 "Win32 "。控制台程序会定义 "_CONSOLE ",否则会定义 "_WINDOWS "。Debug版定义 "_DEBUG ",Release版定义 "NDEBUG " 

与MFC   DLL有关的编译常数包括: 
_WINDLL   表示要做一个用到MFC的DLL 
_USRDLL   表示做一个用户DLL(相对MFC扩展DLL而言)   
_AFXDLL   表示使用MFC动态链接库 
_AFXEXT   表示要做一个MFC扩展DLL 
所以: 
Regular,   statically   linked   to   MFC   _WINDLL,_USRDLL   
Regular,   using   the   shared   MFC   DLL   _WINDLL,_USRDLL,_AFXDLL 
Extension   DLL   _WINDLL,_AFXDLL,_AFXEXT 

CL.EXE编译所有源文件,LINK.EXE链接EXE和DLL,LIB.EXE产生静态库。 

3、subsystem和可执行文件的启动 
LINK的时候需要指定/subsystem,这个链接选项告诉Windows如何运行可执行文件。 
控制台程序是/subsystem: "console " 
其它程序一般都是/subsystem: "windows   " 

将   subsystem   选成 "console "后,Windows在进入可执行文件的代码前(如mainCRTStartup),就会产生一个控制台窗口。 
如果选择 "windows ",操作系统就不产生console窗口,该类型应用程序的窗口由用户自己创建。 

可执行文件都有一个Entry   Point,LINK时可以用/entry指定。缺省情况下,如果subsystem是“console”,Entry   Point是   mainCRTStartup(ANSI)或wmainCRTStartuup(UNICODE),即: 
/subsystem: "console "   /entry: "mainCRTStartup "   (ANSI) 
/subsystem: "console "   /entry: "wmainCRTStartuup "   (UNICODE) 
mainCRTStartup   或   wmainCRTStartuup   会调用main或wmain。 
值得一提的是,在进入应用程序的Entry   Point前,Windows的装载器已经做过C变量的初始化,有初值的全局变量拥有了它们的初值,没有初值的变量被设为0。 

如果subsystem是“windows”,Entry   Point是WinMain(ANSI)或wWinMain(UINCODE),即: 
/subsystem: "windows "   /entry: "WinMainCRTStartup "   (ANSI) 
/sbusystem: "windows "   /entry: "wWinMainCRTStartup "   (UINCODE) 
WinMainCRTStartup   或   wWinMainCRTStartup   会调用   WinMain   或   wWinMain。 

如果使用MFC框架,WinMain也会被埋藏在MFC库中(APPMODUL.CPP): 
extern   "C "   int   WINAPI 
_tWinMain(HINSTANCE   hInstance,   HINSTANCE   hPrevInstance, 
LPTSTR   lpCmdLine,   int   nCmdShow) 
{ 
//   call   shared/exported   WinMain 
return   AfxWinMain(hInstance,   hPrevInstance,   lpCmdLine,   nCmdShow); 

"_t "是一个宏,对于ANSI版本, "_tWinMain "就是 "WinMain ";对于UINCODE版本, "_tWinMain "就是 "wWinMain "。 

全局C++对象的构造函数是在什么地方调用的?答案是在进入应用程序的Entry   Point后,在调用main函数前的初始化操作中。所以MFC的theApp的构造函数是在_tWinMain之前调用的。 


4、不显示Console窗口的Console程序 
在默认情况下/subsystem   和/entry开关是匹配的,也就是: 
"console "对应 "mainCRTStartup "或者 "wmainCRTStartup " 
"windows "对应 "WinMain "或者 "wWinMain " 
我们可以通过手动修改的方法使他们不匹配。例如: 

#include   "windows.h " 
#pragma   comment(   linker,   "/subsystem:\ "windows\ "   /entry:\ "mainCRTStartup\ " "   )   //   设置入口地址   
void   main(void) 
{ 
MessageBox(NULL,   "hello ",   "Notice ",   MB_OK); 


这个Console程序就不会显示Console窗口。如果选/MLd的话,这个程序只需要链接LIBCD.LIB   user32.lib   kernel32.lib。 

5、VC中缺省库冲突的解决 
VC的编译器在编译程序时有两个习惯: 
a、在从头开始编译时,将源文件名按字母排序后,依次处理; 
b、一边编译一边决定需要哪些缺省库。   
它的这些习惯有时会造成奇怪的编译错误,例如项目中有两个文件: 
charutil.c 
gbnni.cpp 
其中gbnni.cpp用到了MFC库。 

它老兄当然是先处理charutil.c,然后觉得需要link一个C   Runtime库,根据项目设置选择了LIBCMTD.lib。 
然后又处理gbnni.cpp,因为要用MFC,又决定要link   nafxcwd.lib。 
最后link的时候,就会出现以下冲突: 
nafxcwd.lib(afxmem.obj)   :   error   LNK2005:   "void   __cdecl   operator   delete(void   *) "   (??3@YAXPAX@Z)   already   defined   in   LIBCMTD.lib(dbgdel.obj) 
其实,如果先link了nafxcwd.lib,就没有必要再link   LIBCMTD.lib,也就不会产生冲突。 

解决这类问题有两个办法。 
a、让项目的第一个文件包含MFC的头文件,这样编译器就不会想到找C   Runtime库。这样就要把c文件改成cpp了。 
b、将需要link   C   Runtime库的文件的名字改大一些,让它排在后面。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值