main函数的前序执行过程简单介绍

main函数的前序执行过程简单介绍

main函数其实是我们能控制的程序入口,但是程序编译之后进行执行却不是从main函数开始的,这里主要讲解下VC6.0++下编译的程序在执行main函数之前的流程,其实主要为在执行main函数之前做了环境变量和参数个数以及参数的解析,然后初始化一些全局变量、堆、io等内容

/***
*crt0.c - C runtime initialization routine
*
*       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       This the actual startup routine for apps.  It calls the user's main
*       routine [w]main() or [w]WinMain after performing C Run-Time Library
*       initialization.
*
*       (With ifdef's, this source file also provides the source code for
*       wcrt0.c, the startup routine for console apps with wide characters,
*       wincrt0.c, the startup routine for Windows apps, and wwincrt0.c,
*       the startup routine for Windows apps with wide characters.)
*
*******************************************************************************/

#ifdef _WIN32

#ifndef CRTDLL

#include <cruntime.h>
#include <dos.h>
#include <internal.h>
#include <stdlib.h>
#include <string.h>
#include <rterr.h>
#include <windows.h>
#include <awint.h>
#include <tchar.h>
#include <dbgint.h>

/*
 * wWinMain is not yet defined in winbase.h. When it is, this should be
 * removed.
 */

int
WINAPI
wWinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPWSTR lpCmdLine,
    int nShowCmd
    );

#ifdef WPRFLAG
_TUCHAR * __cdecl _wwincmdln(void);
#else  /* WPRFLAG */
_TUCHAR * __cdecl _wincmdln(void);
#endif  /* WPRFLAG */

/*
 * command line, environment, and a few other globals
 */

#ifdef WPRFLAG
wchar_t *_wcmdln;           /* points to wide command line */
#else  /* WPRFLAG */
char *_acmdln;              /* points to command line */
#endif  /* WPRFLAG */

char *_aenvptr = NULL;      /* points to environment block */
wchar_t *_wenvptr = NULL;   /* points to wide environment block */


void (__cdecl * _aexit_rtn)(int) = _exit;   /* RT message return procedure */

static void __cdecl fast_error_exit(int);   /* Error exit via ExitProcess */

/*
 * _error_mode and _apptype, together, determine how error messages are
 * written out.
 */
int __error_mode = _OUT_TO_DEFAULT;
#ifdef _WINMAIN_
int __app_type = _GUI_APP;
#else  /* _WINMAIN_ */
int __app_type = _CONSOLE_APP;
#endif  /* _WINMAIN_ */


/***
*BaseProcessStartup(PVOID Peb)
*
*Purpose:
*       This routine does the C runtime initialization, calls main(), and
*       then exits.  It never returns.
*
*Entry:
*       PVOID Peb - pointer to Win32 Process Environment Block (not used)
*
*Exit:
*       This function never returns.
*
*******************************************************************************/

#ifdef _WINMAIN_

#ifdef WPRFLAG
void wWinMainCRTStartup(
#else  /* WPRFLAG */
//此处就是在main函数之前的入口
void WinMainCRTStartup(
#endif  /* WPRFLAG */

#else  /* _WINMAIN_ */

#ifdef WPRFLAG
void wmainCRTStartup(
#else  /* WPRFLAG */
void mainCRTStartup(
#endif  /* WPRFLAG */

#endif  /* _WINMAIN_ */
        void
        )

{
        int mainret;

#ifdef _WINMAIN_
        _TUCHAR *lpszCommandLine;
        STARTUPINFO StartupInfo;
#endif  /* _WINMAIN_ */

        /*
         * Get the full Win32 version
         */
         //首先获取操作系统的版本信息
        _osver = GetVersion();
		//内部的版本号这边是采取位运算来得到的
        _winminor = (_osver >> 8) & 0x00FF ;
        _winmajor = _osver & 0x00FF ;
        _winver = (_winmajor << 8) + _winminor;
        _osver = (_osver >> 16) & 0x00FFFF ;

#ifdef _MT
	   //初始化堆环境
        if ( !_heap_init(1) )               /* initialize heap */
#else  /* _MT */
        if ( !_heap_init(0) )               /* initialize heap */
#endif  /* _MT */
            fast_error_exit(_RT_HEAPINIT);  /* write message and die */

#ifdef _MT
        //如果支持多线程就初始化多线程的环境
        if( !_mtinit() )                    /* initialize multi-thread */
            fast_error_exit(_RT_THREAD);    /* write message and die */
#endif  /* _MT */

        /*
         * Guard the remainder of the initialization code and the call
         * to user's main, or WinMain, function in a __try/__except
         * statement.
         */

        __try {
			//初始化IO	
            _ioinit();                      /* initialize lowio */

#ifdef WPRFLAG
            /* get wide cmd line info */
            //这里就是取得命令行,这里是宽字节版本
            _wcmdln = (wchar_t *)__crtGetCommandLineW();

            /* get wide environ info */
            //这边取得环境变量,取得变量是以空格分开的
            _wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();
           //此处就是初始化main函数的argv参数
            _wsetargv();
            //此处进行环境变量的设置
            _wsetenvp();
#else  /* WPRFLAG */
            //这边就是非宽字节版本的处理流程
            /* get cmd line info */
            _acmdln = (char *)GetCommandLineA();

            /* get environ info */
            _aenvptr = (char *)__crtGetEnvironmentStringsA();

            _setargv();
            _setenvp();
#endif  /* WPRFLAG */
            //此处就是进行初始化浮点寄存器,初始化标准库需要支持的全局对象和用户自定义的对象
            _cinit();                       /* do C data initialize */
//根据WINMAIN宏来设置应用程序是GUI程序还是控制台程序  
#ifdef _WINMAIN_
            StartupInfo.dwFlags = 0;
            //获取进程的启动状态
            GetStartupInfo( &StartupInfo );

#ifdef WPRFLAG
            //这里还是根据宽字节是Unicode版本还是非Unicode版本进行处理
            lpszCommandLine = _wwincmdln();
            mainret = wWinMain(
#else  /* WPRFLAG */
            lpszCommandLine = _wincmdln();
            mainret = WinMain(
#endif  /* WPRFLAG */
                               GetModuleHandleA(NULL),
                               NULL,
                               lpszCommandLine,
                               StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                                    ? StartupInfo.wShowWindow
                                    : SW_SHOWDEFAULT
                             );
#else  /* _WINMAIN_ */

#ifdef WPRFLAG
           //这里是根据是否是控制台程序来进行调用main函数
            __winitenv = _wenviron;
            mainret = wmain(__argc, __wargv, _wenviron);
#else  /* WPRFLAG */
            __initenv = _environ;
            mainret = main(__argc, __argv, _environ);
#endif  /* WPRFLAG */

#endif  /* _WINMAIN_ */
 //此处进行退出main函数
  exit(mainret);
      }
  //此处使用了windows的异常处理机制(SEH),而过滤函数_XcptFilter 首先会检查设置了异常处理函数,如果用户设置了异常处理,就首先会调用用户设置的异常处理函数
  //GetExceptionCode 返回发生的异常的标识
  //每一个SEH异常都有一个与其相关联的异常码(exception code)。你可以使用GetExceptionCode()函数来获取异常码。你可以通过GetExceptionInformation()来获取异常信息
  __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
        {
            /*
             * Should never reach here
             */
             //退出 
            _exit( GetExceptionCode() );

        } /* end of try - except */
}

关于_XcptFilter函数其实就是识别异常并采取相关操作

int __cdecl _XcptFilter(
unsigned long xcptnum,
PEXCEPTION_POINTERS pxcptinfoptrs
);
[in] xcptnum
异常标识符。
[in] pxcptinfoptrs
指向异常信息的指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值