b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

tls现代的应用程序都运行在一个内存空间里,在32位的系统里(5)

电脑杂谈  发布时间:2018-02-13 20:45:13  来源:网络整理

2.1.1 程序从main开始吗

程序从main开始。但是事情的真相真是如此吗?

例如:

#include<stdio.h>
#include<stdlib.h>

int a=3;

int main(int argc,char* argv[])
{
    int *p=(int*) malloc(sizeof(int));
    scanf("%d",p);
    printf("%d",a+b);
    free(p);
}

从代码中我们可以看到,在程序刚刚执行到main的时候,全局变量的初始化过程已经完成了,main函数的两个参数也被正确传了进来。此外在你不知道的时候,堆和栈的初始化悄悄完成了,一些系统I/O也被初始化了,因此可以放心的使用printf和malloc。

例如,在C++里,main之前能够执行的代码会更多。

#include<string>
using namespace std;
string v;

double foo()
{    
    return 1.0;
}

doble g=foo();

int main()
{
}

在这里,对象v的构造函数,以及用于初始化全局变量g的函数foo都会在main之前调用。

例如:

atexti也是一个特殊的函数。atexit接受一个函数指针作为参数,并保证在程序正常退出(指从main里返回或调用exit函数)时,这个函数指针指向的函数会被调用。例如:

void foo(void)
{
    printf("bye!\n";
}

int main()
{
    atexit(&foo);
    printf("endof main\n");
}

用atexit函数注册的函数的调用时机是在main结束之后,因此这段代码的输出时:

endof main

byte!

所有这些例子都证明:操作系统装载程序之后,首先运行的代码不是main的第一 行,而是某些别的代码,这些代码负责准备好main函数执行所需要的环境,并且负责调用main函数,这时候你才可以在main函数里大胆地写各种代码: 申请内存、使用系统调用、触发异常、访问I/O。在main返回之后,它会记录main函数的返回值,调用atexit注册的函数,然后结束进程。

运行这些代码的函数称为入口函数和入口点。一个典型的程序运行步骤如下:

1)操作系统在创建进程后,把控制权交到了程序的入口,这个入口往往是运行库中的某个入口函数。

2)入口函数对运行库和程序运行环境进行初始化,包括堆、I/O、线程、全局变量构造等等。

3)入口函数在完成初始化之后,调用main函数,正式开始执行程序主体部分

4)main函数完成以后,返回到入口函数,入口函数进行清理工作,包括全局变量析构、对摧毁、关闭I/O等,然后进行系统调用结束进程。

2.1.2 入口函数如何实现

glibc的启动过程在不同的情况下差别很大,比如静态glibc和动态glibc的区别,glibc用于可执行文件好用于共享文件的差别。这里只取最简单的静态glibc用于可执行文件的例子。tls

glibc的程序入口为_start(这个入口是由ld链接器默认的链接脚本所指定的,我们也可以通过相关参数设定自己的入口)。tls_start由汇编器实现,并且和平台相关。

可以看到_start函数最终调用了名为_lib_start_main的函数。其实在调用_start前,装载器会把用户的参数和环境变量压入栈中,按照其压栈的方法,实际上栈顶的元素是argc,而接下来其下就是argv和环境变量的数组。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-76057-5.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...