游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3038|回复: 5

程序是怎么开始运行的.

[复制链接]

89

主题

4036

帖子

4132

积分

论坛元老

Rank: 8Rank: 8

积分
4132
发表于 2004-8-10 16:43:00 | 显示全部楼层 |阅读模式
很多人都知道一个C程序是从main函数开始的。
main函数是系统调用这个函数,然后程序开始运行的.

可事实上是这样的吗?
其实不是,
正真的源头.我也不知道。 但是有一点是肯定的.main不是源头.
main 是由mainCRTStartup调用的。 而winmian是由WinMainCRTStartup调用的.
以下是Crt0.c里得到的代码. VC.NET版本.


#ifdef _WINMAIN_

#ifdef WPRFLAG
int wWinMainCRTStartup(
#else  /* WPRFLAG */
int WinMainCRTStartup(
#endif  /* WPRFLAG */

#else  /* _WINMAIN_ */

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

#endif  /* _WINMAIN_ */

        void
        )

{
        int initret;
        int mainret;
        OSVERSIONINFOA *posvi;
        int managedapp;
#ifdef _WINMAIN_
        _TUCHAR *lpszCommandLine;
        STARTUPINFO StartupInfo;
#endif  /* _WINMAIN_ */
        /*
         * Dynamically allocate the OSVERSIONINFOA buffer, so we avoid
         * triggering the /GS buffer overrun detection.  That can't be
         * used here, since the guard cookie isn't available until we
         * initialize it from here!
         */
        posvi = (OSVERSIONINFOA *)_alloca(sizeof(OSVERSIONINFOA));

        /*
         * Get the full Win32 version
         */
        posvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
        (void)GetVersionExA(posvi);

        _osplatform = posvi->dwPlatformId;
        _winmajor = posvi->dwMajorVersion;
        _winminor = posvi->dwMinorVersion;

        /*
         * The somewhat bizarre calculations of _osver and _winver are
         * required for backward compatibility (used to use GetVersion)
         */
        _osver = (posvi->dwBuildNumber) & 0x07fff;
        if ( _osplatform != VER_PLATFORM_WIN32_NT )
            _osver |= 0x08000;
        _winver = (_winmajor << 8) + _winminor;

        /*
         * Determine if this is a managed application
         */
        managedapp = check_managed_app();

#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 */

        /*
         * Initialize the Runtime Checks stuff
         */
#ifdef _RTC
        _RTC_Initialize();
#endif  /* _RTC */
        /*
         * Guard the remainder of the initialization code and the call
         * to user's main, or WinMain, function in a __try/__except
         * statement.
         */

        __try {

            if ( _ioinit() < 0 )            /* initialize lowio */
                _amsg_exit(_RT_LOWIOINIT);

#ifdef WPRFLAG
            /* get wide cmd line info */
            _wcmdln = (wchar_t *)__crtGetCommandLineW();

            /* get wide environ info */
            _wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();

            if ( _wsetargv() < 0 )
                _amsg_exit(_RT_SPACEARG);
            if ( _wsetenvp() < 0 )
                _amsg_exit(_RT_SPACEENV);
#else  /* WPRFLAG */
            /* get cmd line info */
            _acmdln = (char *)GetCommandLineA();

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

            if ( _setargv() < 0 )
                _amsg_exit(_RT_SPACEARG);
            if ( _setenvp() < 0 )
                _amsg_exit(_RT_SPACEENV);
#endif  /* WPRFLAG */

            initret = _cinit(TRUE);                  /* do C data initialize */
            if (initret != 0)
                _amsg_exit(initret);

#ifdef _WINMAIN_

            StartupInfo.dwFlags = 0;
            GetStartupInfo( &StartupInfo );

#ifdef WPRFLAG
            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
            __winitenv = _wenviron;
            mainret = wmain(__argc, __wargv, _wenviron);
#else  /* WPRFLAG */
            __initenv = _environ;
            mainret = main(__argc, __argv, _environ);
#endif  /* WPRFLAG */

#endif  /* _WINMAIN_ */

            if ( !managedapp )
                exit(mainret);

            _cexit();

        }
        __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
        {
            /*
             * Should never reach here
             */

            mainret = GetExceptionCode();

            if ( !managedapp )
                _exit(mainret);

            _c_exit();

        } /* end of try - except */

        return mainret;
}

50

主题

992

帖子

1012

积分

金牌会员

Rank: 6Rank: 6

积分
1012
发表于 2004-8-10 16:49:00 | 显示全部楼层

Re:程序是怎么开始运行的.

main函数只是程序的入口点,它是由系统中的装载器加载并启动的

8

主题

553

帖子

560

积分

高级会员

Rank: 4

积分
560
发表于 2004-8-10 18:33:00 | 显示全部楼层

Re:程序是怎么开始运行的.

是啊,main不是程序最开始执行的地方。
大概的说,对于C,在main执行前要进行c runrime初始化,对于C++,还要进行全局/静态变量的初始化呢,所以千万不要以为main的第一行代码是最先执行的。

89

主题

4036

帖子

4132

积分

论坛元老

Rank: 8Rank: 8

积分
4132
 楼主| 发表于 2004-8-12 00:44:00 | 显示全部楼层

Re:程序是怎么开始运行的.

附加一句,按F11运行程序.可以看到CRT的代码.在VS.NET里。当然.用这个方法也可以看到MFC的代码.当前我就是这么读MFC的代码的。慢慢的跟进去.

28

主题

433

帖子

433

积分

中级会员

Rank: 3Rank: 3

积分
433
发表于 2004-8-12 10:21:00 | 显示全部楼层

Re:程序是怎么开始运行的.

有必要了解这么清楚吗?

4

主题

25

帖子

25

积分

注册会员

Rank: 2

积分
25
QQ
发表于 2004-8-12 18:58:00 | 显示全部楼层

Re:程序是怎么开始运行的.

这个在调试程序时,是很有用的!

“还要进行全局/静态变量的初始化呢”,有的时候,程序就会这些全局变量里出错了!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-8-16 13:50

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表