上一节详细介绍了/MT /MD之间的区别。在这一节中,我们首先要找到win32程序真正的启动函数。
win32程序分为两种:
1.控制台(/SUBSYSTEM:CONSOLE )
2.GUI(/SUBSYSTEM:WINDOWS)
首先看控制台版本的:
写一段最简单的,或者就直接使用编译器参数的默认main函数,如下:
// EntryFunction.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
1.使用/MD选项
F9下断到main函数的标签处,F11后,在Call Stack中回溯到_tmainCRTStartup(),当前文件为crtexe.c。如下:
2.使用/MT选项
F9下断到main函数的标签处,F11后,在Call Stack中回溯到_tmainCRTStartup(),当前文件为crt0.c。如下:
也就是说,不同的运行时链接方式,其实现代码也是不同的。但是其入口点函数的名称是相同的,都是_tmainCRTStartup。这便是Windows下的启动函数(真正的入口函数)。
下面我们分别讨论,这两者在入口函数中都干了些什么。
首先看_security_init_cookie,这个函数在两个实现文件中是一样的,代码如下:
/***
*__security_init_cookie(cookie) - init buffer overrun security cookie.
*
*Purpose:
* Initialize the global buffer overrun security cookie which is used by
* the /GS compile switch to detect overwrites to local array variables
* the potentially corrupt the return address. This routine is called
* at EXE/DLL startup.
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl __security_init_cookie(void)
{
UINT_PTR cookie;
FT systime={0};
LARGE_INTEGER perfctr;
/*
* Do nothing if the global cookie has already been initialized. On x86,
* reinitialize the cookie if it has been previously initialized to a
* value with the high word 0x0000. Some versions of Windows will init
* the cookie in the loader, but using an older mechanism which forced the
* high word to zero.
*/
if (__security_cookie != DEFAULT_SECURITY_COOKIE
#if defined (_M_IX86)
&& (__security_cookie & 0xFFFF0000) != 0
#endif /* defined (_M_IX86) */
)
{
__security_cookie_complement = ~__security_cookie;
return;
}
/*
* Initialize the global cookie with an unpredictable value which is
* different for each module in a process. Combine a number of sources
* of randomness.
*/
GetSystemTimeAsFileTime(&systime.ft_struct);
#if defined (_WIN64)
cookie = systime.ft_scalar;
#else /* defined (_WIN64) */
cookie = systime.ft_struct.dwLowDateTime;
cookie ^= systime.ft_struct.dwHighDateTime;
#endif /* defined (_WIN64) */
cookie ^= GetCurrentThreadId();
cookie ^= GetCurrentProcessId();
#if _CRT_NTDDI_MIN >= NTDDI_VISTA
#if defined (_WIN64)
cookie ^= (((UINT_PTR)GetTickCount64()) << 56);
#endif /* defined (_WIN64) */
cookie ^= (UINT_PTR)GetTickCount64();
#endif /* _CRT_NTDDI_MIN >= NTDDI_VISTA */
QueryPerformanceCounter(&perfctr);
#if defined (_WIN64)
cookie ^= (((UINT_PTR)perfctr.LowPart << 32) ^ perfctr.QuadPart);
#else /* defined (_WIN64) */