main函数执行前发生了什么
2017-10-24 17:45
204 查看
main函数的身前
1. 编译器缺省是找__start
符号,而不是 main
2. __start 这个符号是程序的起始点
3. main 是被标准库调用的一个符号
我们写程序,比如一个模块,通常要有 initialize
和de-initialize,但是我们写 C
程序的时候为什么有些模块没有这两个过程么呢?比如我们程序从main
开始就可以 malloc,free,但是我们在main
里面却没有初始化堆。再比如在 main
里面可以直接printf,可是我们并没有打开标准输出文件啊。(不知道什么是stdin,stdout,stderr以及
printf 和stdout
关系的群众请先看看 C
语言中文件的概念)。
我们会在编译器的环境中找到一个名字类似于 crt0.o的文件,这个文件中包含了我们刚才所说的__start
符号。(crt
大概是C Runtime
的缩写,请大家帮助确认一下。)
那么真正的 crt0.s
是什么样子呢?下面我们给出部分伪代码:
section .text:
__start:
:
init stack;
init heap;
open stdin;
open stdout;
open stderr;
:
push argv;
push argc;
call _main; (调用main)
:
destory heap;
close stdin;
close stdout;
close stderr;
:
call __exit;
////////////////////////////////////////////////////
注意:
1. 不同的编译器,不一定缺省得符号都是__start。
2. 汇编里面的_main
就是 C
语言里面的main,是因为汇编器和C编译器对符号的命名有差异(通常是差一个下划线'_')。
3. 目前操作系统结构有两个主要的分支:微内核和宏内核。微内核的优点是,结构清晰,简单,内核组件较少,便于维护;缺点是,进程间通信较多,程序频繁进出内核,效率较低。宏内核正好相反。我说这个是什么目的是:没办法保证每个组件都在用户空间(标准库函数)中初始化,有些组件确实可能不要初始化,操作系统在创建进程的时候在内核空间做的。这依赖于操作系统的具体实现,比如堆,宏内核结构可能在内核初始化,微内核结构在用户空间;即使同样是微内核,这个东东也可能会被拿到内核空间初始化。
随着 CPU
技术的发展,存储量的迅速扩展,代码复杂程度的增加,微内核被越来越多的采用。你会为了10%
的效率使代码复杂度增加么?要知道每隔 18
个月CPU
的速度就会翻一番。所以我对程序员的要求是,我首先不要你的代码效率高,我首先要你的代码能让80%
的人迅速看懂并可以维护。
总结:
main函数执行之前,主要就是初始化系统相关资源:
1.设置栈指针
2.初始化static静态和global全局变量,即data段的内容
3.将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容
4.运行全局构造器,估计是C++中构造函数之类的吧
5.将main函数的参数,argc,argv等传递给main函数,然后才真正运行main函数
1. 编译器缺省是找__start
符号,而不是 main
2. __start 这个符号是程序的起始点
3. main 是被标准库调用的一个符号
我们写程序,比如一个模块,通常要有 initialize
和de-initialize,但是我们写 C
程序的时候为什么有些模块没有这两个过程么呢?比如我们程序从main
开始就可以 malloc,free,但是我们在main
里面却没有初始化堆。再比如在 main
里面可以直接printf,可是我们并没有打开标准输出文件啊。(不知道什么是stdin,stdout,stderr以及
printf 和stdout
关系的群众请先看看 C
语言中文件的概念)。
我们会在编译器的环境中找到一个名字类似于 crt0.o的文件,这个文件中包含了我们刚才所说的__start
符号。(crt
大概是C Runtime
的缩写,请大家帮助确认一下。)
那么真正的 crt0.s
是什么样子呢?下面我们给出部分伪代码:
section .text:
__start:
:
init stack;
init heap;
open stdin;
open stdout;
open stderr;
:
push argv;
push argc;
call _main; (调用main)
:
destory heap;
close stdin;
close stdout;
close stderr;
:
call __exit;
////////////////////////////////////////////////////
注意:
1. 不同的编译器,不一定缺省得符号都是__start。
2. 汇编里面的_main
就是 C
语言里面的main,是因为汇编器和C编译器对符号的命名有差异(通常是差一个下划线'_')。
3. 目前操作系统结构有两个主要的分支:微内核和宏内核。微内核的优点是,结构清晰,简单,内核组件较少,便于维护;缺点是,进程间通信较多,程序频繁进出内核,效率较低。宏内核正好相反。我说这个是什么目的是:没办法保证每个组件都在用户空间(标准库函数)中初始化,有些组件确实可能不要初始化,操作系统在创建进程的时候在内核空间做的。这依赖于操作系统的具体实现,比如堆,宏内核结构可能在内核初始化,微内核结构在用户空间;即使同样是微内核,这个东东也可能会被拿到内核空间初始化。
随着 CPU
技术的发展,存储量的迅速扩展,代码复杂程度的增加,微内核被越来越多的采用。你会为了10%
的效率使代码复杂度增加么?要知道每隔 18
个月CPU
的速度就会翻一番。所以我对程序员的要求是,我首先不要你的代码效率高,我首先要你的代码能让80%
的人迅速看懂并可以维护。
总结:
main函数执行之前,主要就是初始化系统相关资源:
1.设置栈指针
2.初始化static静态和global全局变量,即data段的内容
3.将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容
4.运行全局构造器,估计是C++中构造函数之类的吧
5.将main函数的参数,argc,argv等传递给main函数,然后才真正运行main函数
相关文章推荐
- [C/C++] main函数执行前后还会发生什么
- [C/C++] main函数执行前后还会发生什么
- main函数之前究竟发生了什么?
- main函数之前究竟发生了什么?
- Qt中同一个线程里,QTimer的timeout()信号相关的槽未执行完,会发生什么?
- MySQL主库大表执行delete语句,Ctrl+C具体发生了什么分析
- main函数之前究竟发生了什么?
- 什么会在main函数之前执行
- iOS程序main函数之前发生了什么
- iOS程序main函数之前发生了什么
- main函数之前会执行什么?
- main函数之前发生了什么
- 当执行php脚本时用户关闭浏览器会发生什么?
- 在页面生命周期执行时 Page 对象在 SaveState 阶段都发生了什么事?
- 执行Java -jar somefile.jar时发生了什么(一)
- 执行 $Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二)
- 执行Java -jar somefile.jar时发生了什么(二)
- Struts2学习(四):Action执行的时候发生了什么
- 程序是如何编译执行的,背后都发生了什么
- 一个空的vector执行pop_back操作会发生什么?