C语言深度总结[全面认识main函数之前运行代码]

一、main运行前可运行哪些代码

  (1)全局对象的构造函数会在main 函数之前执行。

  (2)一些全局变量、对象和静态变量、对象的空间分配和赋初值就是在执行main函数之前,而main函数执行完后,还要去执行一些诸如释放空间、释放资源使用权等操作

  (3)进程启动后,要执行一些初始化代码(如设置环境变量等),然后跳转到main执行。全局对象的构造也在main之前。

  (4)通过关键字__attribute__,让一个函数在主函数之前运行,进行一些数据初始化、模块加载验证等。

main函数运行之前需要运行的逻辑(为了保持原味,我就不翻译了)

Some of the stuff that has to happen before main():

set up initial stack pointer 

initialize static and global data 

zero out uninitialized data 

run global constructors

Some of this comes with the runtime library's crt0.o file or its __start() function. Some of it you need to do yourself.

Crt0 is a synonym for the C runtime library.

Depending on the system you're using the follwing may be incomplete, but it should give you an idea. Using newlib-1.9.0/libgloss/m68k/crt0.S as an outline, the steps are:

1. Set stack pointer to value of __STACK if set 

2. Set the initial value of the frame pointer 

3. Clear .bss (where all the values that start at zero go) 

4. Call indirect of hardware_init_hook if set to initialize hardware 

5. Call indirect of software_init_hook if set to initialize software 

6. Add __do_global_dtors and __FINI_SECTION__ to the atexit function so destructors and other cleanup functions are called when the program exits by either returning from main, or calling exit

7. setup the paramters for argc, argv, argp and call main 

8. call exit if main returns

谁调用了我的main函数

我们都听说过一句话:“main是C语言的入口”。我至今不明白为什么这么说。就好像如果有人说:“挣钱是泡妞”,肯定无数砖头拍过来。这句话应该是“挣钱是泡妞的一个条件,只不过这个条件特别重要”。那么上面那句话应该是 “main是C语言中一个符号,只不过这个符号比较特别。”

我们看下面的例子:

    /* file name battle.c */

    #include<stdio.h>

    int main(int argc, char* argv[])

    {

                printf("老铁,感谢有缘一起学习C语言,除了跟着这套课程走,为了更好地解决大家实操中的问题,可以加QQ群676593534,及时交流。群里还有很多精致资料哦,我这这里等你!");

     return 0;

    }

编译链接它:

cc battle.c -o test.exe

会生成 test.exe

但是我们加上这个选项: -nostdlib (不链接标准库)

cc battle.c-nostdlib -o test.exe

链接器会报错:

undefined symbol: __start

也就是说:

1. 编译器缺省是找 __start 符号,而不是 main

2. __start 这个符号是程序的起始点

3. main 是被标准库调用的一个符号

继续探索

 我们写程序,比如一个模块,通常要有 initialize 和 de-initialize,但是我们写 C 程序的时候为什么有些模块没有这两个过程么呢?比如我们程序从 main 开始就可以 malloc,free,但是我们在 main 里面却没有初始化堆。再比如在 main 里面可以直接 printf,可是我们并没有打开标准输出文件啊。(不知道什么是 stdin,stdout,stderr 以及 printf 和 stdout 关系的群众请先看看 C 语言中文件的概念)。

有人说,这些东西不需要初始化。如果你真得这么想,有点率性而为了。

  聪明的人民群众会想,一定是在 main 之前干了些什么。使这些函数可以直接调用而不用初始化。通常,我们会在编译器的环境中找到一个名字类似于 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编译器对符号的命名有差异(通常是差一个下划线'_')。

Demo演示

#include <stdio.h>

#if 0

The constructor attribute causes the function to be called automatically before 

execution enters main (). Similarly, the destructor attribute causes the function 

to be called automatically after main () completes or exit () is called. 

Functions with these attributes are useful for initializing data that is used 

implicitly during the execution of the program.

more infoformation: https://gcc.gnu.org/onlinedocs/gcc-6.2.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes

#endif 


__attribute__((constructor)) void before_main_to_run() 

    printf("Hi~,i am called before the main function!\n");

    printf("%s\n",__FUNCTION__); 

__attribute((constructor)) void before_main_to_run_two() 

    printf("Hi~,i am called before the main function!\n");

    printf("%s\n",__FUNCTION__); 


__attribute__((destructor)) void after_main_to_run() 

    printf("%s\n",__FUNCTION__); 

    printf("Hi~,i am called after the main function!\n");


__attribute((destructor)) void after_main_to_run_two() 

    printf("%s\n",__FUNCTION__); 

    printf("Hi~,i am called after the main function!\n");

int main( int argc, char ** argv ) 

    printf("i am main function, and i can get my name(%s) by this way.\n",__FUNCTION__); 

    return 0; 

总结

main函数执行之前,主要就是初始化系统相关资源:

1.设置栈指针

2.初始化static静态和global全局变量,即data段的内容

3.将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容

4.将main函数的参数,argc,argv等传递给main函数,然后才真正运行main函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,102评论 0 10
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,517评论 0 38
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,615评论 0 3
  • 虫忘记了尘埃。 神忘记了永恒。 我还是想坚持自己的生存法则。 在冷漠的世界里,深情地活着。 在颓废的环境中,热血地...
    蜗牛36阅读 101评论 0 0
  • # 老罗语录 每个生命来到世间,都注定改变世界,别无选择。要么变的好一点,要么变的坏一点。你如果走进社会为了生存,...
    行与心田阅读 572评论 0 0