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

2023-11-11

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
指向异常信息的指针。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

main函数的前序执行过程简单介绍 的相关文章

  • 【vue】vue组件之间相互调用问题处理

    背景 最近再使用抽屉组件的时候 遇到一个棘手的问题 就是抽屉是座位详情功能使用的 这就会带来一个问题 可能在 用户详情抽屉 中需要调用 订单详情抽屉 而 订单详情抽屉 也可能调用 用户详情抽屉 简单来说过就是A组件调用B组件 B组件又调用A
  • 私有化部署即时通讯平台,完美替代飞书和钉钉的SaaS系统

    在当今快速发展的数字化时代 企业对于安全 灵活 可定制的即时通讯平台需求不断增长 作为一家领先的品牌 WorkPlus专注于提供私有化部署的即时通讯平台 完美替代飞书和钉钉的SaaS系统 本文将重点介绍WorkPlus如何通过创新的解决方案
  • iOS开发中的敏捷方法

    敏捷开发是现在比较流行的软件开发方法 因为方法决定效率 好的方法可以大大地提高开发效率 什么是敏捷 Agile 敏捷源于2001年美国犹他州雪鸟滑雪圣地的一次聚会 聚会是敏捷方法发起者和实践者的聚会 他们经过两天的讨论 通一份简明扼要的 敏
  • ExtJS Sencha CMD 打包异常报错分析处理 - 2

    今天使用 sencha app build testing 进行编译 然后运行的时候 出现错误 app js dc 1666874035180 81578 Uncaught TypeError t 1 is not a function a
  • yar框架的并行原理分析(libcurl+epoll)

    yar是一个轻量级的php rpc框架 有意思的是它的并行 其实就是libcurl作为网络库提供http请求 然后用epoll做为事件监听来实现整个异步并行调用的 在此基础上 就是如何利用zend api来对整个逻辑的封装了 我们先抛开ze
  • 平衡小车调试总结及心得

    目录 一 知识点 1 PID控制算法 2 平衡原理 二 硬件 1 编码器 2 电机 3 PWM 4 陀螺仪MPU6050 三 PID调节过程 1 理论部分 1 1直立环 1 2速度环 串级PID 1 3 纯比例控制 2 调参步骤 2 1大致

随机推荐

  • sql注入之万能密码总结

    sql注入之万能密码总结 万能密码 万能密码原理 万能密码 asp aspx万能密码 PHP万能密码 jsp 万能密码 万能密码 啊这 一般用来ctf登录的时候试试 这是sqli labs用的时候 我来记录一下 万能密码原理 原验证登陆语句
  • Python基础——函数的基本使用

    文章目录 一 定义 二 属性 三 操作 1 函数的参数 2 函数返回值 3 函数多个返回值 4 多个return语句 5 函数调用函数 6 函数的联系及注释 7 局部变量和全局变量 8 数据的传递 9 lambda表达式 一 定义 1 语法
  • 【TensorFlow】TensorFlow函数精讲之 tf.nn.relu()

    tf nn relu 函数是将大于0的数保持不变 小于0的数置为0 函数如图1所示 ReLU函数是常用的神经网络激活函数之一 图1 ReLU函数图像 下边为ReLU例子 import tensorflow as tf v tf consta
  • 自动控制原理与动态系统的建模与分析

    1 开环系统和闭环系统 反馈控制 1 1开环控制 开环控制系统是指无被控量反馈的系统 即在系统中控制信息的流动未形成闭合回路 1 2 闭环控制 有被控量反馈的控制 即系统的输出信号沿反馈通道又回到系统的输入端 构成闭合通道 也叫做反馈控制
  • go get国内解决办法汇总

    go作为Google大佬的亲儿子 go开发过程中除了SDK自带的包外还经常会需要用到大佬提供的其他包 这些包都在golang org下 而下载这些包需要访问大佬的服务器 国内开发者就会遇到各种的问题 今天就给大家总结一下有哪些途径安装这些包
  • Android Studio Flutter 开发配置

    近来比较闲 就研究下Flutter 开发 在此记录下studio 配置过程 时间是2023 7 19 在 Windows 操作系统上安装和配置 Flutter 开发环境 1 首先下载 Flutter SDKhttps storage flu
  • 基于51单片机水塔水箱液水位WIFI监控报警设计proteus仿真原理图PCB

    功能 0 本项目采用STC89C52作为单片机系统的控制MCU 1 WIFI实时上传当前水位状态 2 通过液位传感器检测液位 检测到最低液位和最高液位时 超过设定阈值将声光报警 3 通过状态指示灯显示当前液位情况 三种颜色 红色代表低于下限
  • python urllib下载文件怎么停止_python下载文件的三种方法

    Python开发中时长遇到要下载文件的情况 最常用的方法就是通过Http利用urllib或者urllib2模块 当然你也可以利用ftplib从ftp站点下载文件 此外Python还提供了另外一种方法requests 下面来看看三种方法是如何
  • unity利用高阶贝塞尔曲线进行的轨道移动

    之前想做一个按照固定的路线进行移动的demo 就想到了路径的曲线 然后就想到了贝塞尔曲线 先上贝塞尔通用公式 借鉴网上的代码和相应的函数公式 组成了一个demo 通用的贝塞尔曲线工具类 using System Collections us
  • elasticsearch基础6——head插件安装和web页面查询操作使用、ik分词器

    文章目录 一 基本了解 1 1 插件分类 1 2 插件管理命令 二 分析插件 2 1 es中的分析插件 2 1 1 官方核心分析插件 2 1 2 社区提供分析插件 2 2 API扩展插件 三 Head 插件 3 1 安装 3 2 web页面
  • Python 基础知识5 元组操作

    元组 与列表不同之处 1 使用 定义 2 定以后元组的元素不能修改 元组定义 只有一个元素时元素后加 号 否则为整型 tup1 hello world 120 123 tup2 1 5 4 2 3 tup3 a b c d tup4 pri
  • Maven项目中读取src/main/resources目录下的配置文件

    在Maven项目的开发中 当需要读取src 下的配置文件时 该怎么做 我们假设Resources下有一个文件名为kafka properties的配置文件 为什么用kafka properties 因为这是在做kafka项目的时候碰到的问题
  • global::System.Runtime.Versioning.TargetFrameworkAttribute 特性重复

    visual studio code 反编译 报错 global System Runtime Versioning TargetFrameworkAttribute 特性重复 在 csproj文件内添加
  • itk.js读取.nii.gz文件,vtk.js进行渲染

    我们只需要用到itk中的 readImageArrayBuffer 从这个api我们可以看出 我们需要的是一个ArrayBuffer的数据 那么 我们通过 vtk js中的vtkHttpDataAccessHelper的方法把数据转换成Ar
  • 提高接口并发量,防止崩溃

    思路 对高并发的接口 单独配置线程池 需考虑线程池内的线程数量 以及tomcat总线程数量与CPU的关系 线程池的配置 接口如何配置单独的线程池 异步任务 Async myExecutors 对实时性要求高的 分析下 实时就是同步 每一次请
  • 如何卸载FF推荐?

    很多小伙伴们都发现 近一段时间 自己的电脑中时常会弹出一个叫 FF新推荐 的广告弹窗 扰民不说显示的内容也很猥亵 按理说 电脑上开启拦截软件后 一般的广告弹窗是不会出现的 那么这个能跳过安全工具拦截的家伙是何背景 能否永久地关闭它 今天小编
  • PingCAP刘奇:如何构建一个NewSQL数据库

    PingCAP刘奇 如何构建一个NewSQL数据库 75 0 0 编者按 6月24日 由香港主办 开源社群主导的国际技术会议 香港开源年会2016 HKOSCon 在港召开 PingCAP 联合创始人兼CEO刘奇应邀出席 与大家分享了 Ho
  • [Unity小游戏]打砖块(打方块)教程(超详细)

    Unity小游戏 打砖块 打方块 超详细 打砖块小游戏通常会被当做Unity学习的第一个案例 下面给大家介绍如何实现打砖块案例的 先来张图看看效果 首先我们要知道QWER分别是选择 移动 旋转 缩放工具的快捷键 英文模式下按住才有用 只有在
  • 计算机学报——主题“区块链”,检索到25篇

    CCF期刊导航https mp weixin qq com s Hu ozQG uoYDLN0jQzUhDQhttps mp weixin qq com s Hu ozQG uoYDLN0jQzUhDQ 按时间排序 序号 篇名 时间 关键词
  • main函数的前序执行过程简单介绍

    main函数的前序执行过程简单介绍 main函数其实是我们能控制的程序入口 但是程序编译之后进行执行却不是从main函数开始的 这里主要讲解下VC6 0 下编译的程序在执行main函数之前的流程 其实主要为在执行main函数之前做了环境变量