看到《windows核心编程》里说C/C++程序实际上都是由运行时库中的Startup系列函数(mainCRTStartup,wmainCRTStartup, WinMainCRTStartup,wWinMainCRTStartup)来执行一系列初始化后,再调用程序员写的代码中的main、wmain、WinMain或wWinMain,于是很想看看mainCRTStartup的定义,书上说是在crt0.c里,可是明明没有嘛。书是在windows2000下写的,可能现在的微软C/C++运行时库已经变化很多了。
把crt0.c的几个包含文件都看了下,还是没找到,看来还是得遍历C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src里面的源码文件来找才行,于是写了一个Python脚本,还挺快的。
import os
def find_file_text(root_dir,target_text):
suffix=['c','cpp','h','hpp','cxx']
for root,dirs,files in os.walk(root_dir):
for file in files:
file_suffix=file[file.find('.')+1:len(file)]
if file_suffix in suffix:
file_obj=open(os.path.join(root, file),'rU')
line_no=0
for eachline in file_obj:
line_no=line_no+1
if eachline.find(target_text)!=-1:
print "%s %d:%s"%(os.path.join(root, file),line_no,eachline)
find_file_text(r'C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src','mainCRTStartup')
终于找到了,原来mainCRTStartup和wmainCRTStartup都是调用的__tmainCRTStartup,在C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\crtexe.c中
#ifdef _WINMAIN_
#ifdef WPRFLAG
int wWinMainCRTStartup(
#else
int WinMainCRTStartup(
#endif
#else
#ifdef WPRFLAG
int wmainCRTStartup(
#else
int mainCRTStartup(
#endif
#endif
void
)
{
__security_init_cookie();
return __tmainCRTStartup();
}
__declspec(noinline)
int
__tmainCRTStartup(
void
)
{
#ifdef _WINMAIN_
_TUCHAR *lpszCommandLine;
STARTUPINFO StartupInfo;
BOOL inDoubleQuote=FALSE;
__try {
GetStartupInfo( &StartupInfo );
} __except(EXCEPTION_EXECUTE_HANDLER) {
return 255;
}
#endif
__try
{
void *lock_free=0;
void *fiberid=((PNT_TIB)NtCurrentTeb())->StackBase;
int nested=FALSE;
while((lock_free=InterlockedCompareExchangePointer((volatile PVOID *)&__native_startup_lock, fiberid, 0))!=0)
{
if(lock_free==fiberid)
{
nested=TRUE;
break;
}
Sleep(1000);
}
if (__native_startup_state == __initializing)
{
_amsg_exit( _RT_CRT_INIT_CONFLICT);
}
else if (__native_startup_state == __uninitialized)
{
__native_startup_state = __initializing;
#ifndef _SYSCRT
if (_initterm_e( __xi_a, __xi_z ) != 0)
{
return 255;
}
#else
_initterm((_PVFV *)(void *)__xi_a, (_PVFV *)(void *)__xi_z);
#endif
}
else
{
has_cctor = 1;
}
if (__native_startup_state == __initializing)
{
_initterm( __xc_a, __xc_z );
__native_startup_state = __initialized;
}
_ASSERTE(__native_startup_state == __initialized);
if(!nested)
{
#pragma warning(push)
#pragma warning(disable:4312)
InterlockedExchangePointer((volatile PVOID *)&__native_startup_lock, 0);
#pragma warning(pop)
}
if (__dyn_tls_init_callback != NULL &&
_IsNonwritableInCurrentImage((PBYTE)&__dyn_tls_init_callback))
{
__dyn_tls_init_callback(NULL, DLL_THREAD_ATTACH, NULL);
}
_CrtSetCheckCount(TRUE);
#ifdef _WINMAIN_
#ifdef WPRFLAG
if (_wcmdln == NULL)
return 255;
lpszCommandLine = (wchar_t *)_wcmdln;
#else
lpszCommandLine = (unsigned char *)_acmdln;
#endif
while (*lpszCommandLine > SPACECHAR ||
(*lpszCommandLine&&inDoubleQuote)) {
if (*lpszCommandLine==DQUOTECHAR) inDoubleQuote=!inDoubleQuote;
#ifdef _MBCS
if (_ismbblead(*lpszCommandLine)) {
if (lpszCommandLine) {
lpszCommandLine++;
}
}
#endif
++lpszCommandLine;
}
while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) {
lpszCommandLine++;
}
#ifdef WPRFLAG
mainret = wWinMain(
#else
mainret = WinMain(
#endif
(HINSTANCE)&__ImageBase,
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
#else
#ifdef WPRFLAG
__winitenv = envp;
mainret = wmain(argc, argv, envp);
#else
__initenv = envp;
mainret = main(argc, argv, envp);
#endif
#endif
if ( !managedapp )
exit(mainret);
if (has_cctor == 0)
_cexit();
}
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
{
mainret = GetExceptionCode();
if ( !managedapp )
_exit(mainret);
if (has_cctor == 0)
_cexit();
}
return mainret;
}
看的头疼,明天再看了。