a.out在运行时都干了什么

    a.out是我们在linux编程环境下最常见的可执行文件了,它是Assembly output的缩写,但它却不是字面意思“汇编输出”,准确的说它是链接器最后输出的产物,延用a.out的写法只是历史原因,大家都不愿意去改了。

    我们都知道程序被编辑编译链接完成后被分段组织存储,文本段+数据段+BSS段+堆栈。下面用一张图更直观的解释a.out在内存中的布局:


                                                       1、 可执行文件在内存中是如何布局的


    数据段包含已初始化的全局变量和静态变量及初始值。BSS段的大小直接由可执行文件中记录的BSS段大小得到,该内存区在在进入程序的地址空间后被全部置零。堆栈段用来存放局部变量、表达式临时数据、函数参数等等。可执行文件的虚拟地址空间的最底部分为被分配,也就是说该部分空间在进程地址空间中,但是没有被分配到实际的物理地址上(没有向文本段数据段那样能找到a.out上的对应段),所以所有对该段空间的引用都是不合法的。一般来说,它都是从地址0开始的几K字节,用于捕捉使用空指针或小整型值的指针引用内存的情况。

    当程序使用动态库时,a.out的虚拟地址空间布局如下图:


                                        2、使用动态库时的可执行文件的虚拟地址空间


    ok,说完a.out的内存分布,就来说说a.out在运行的时候内存上有哪些东西在活动。

    可执行文件在运行时的数据结构包括堆、栈、数据、过程活动记录(precedure activation recored).以下作简要介绍,因为有些知识点早已烂大街。

    栈为的局部变量和临时变量提供空间,也可是使用alloca()函数来分配在栈中的内存,使用完自动释放。

    堆上的空间可以在整个程序的生命周期一直存在。

    过程活动记录是一种数据结构,用于支持过程调用,记录调用结束后返回调用点的所有信息。


上图即过程活动记录所包括的成员描述。关于静态链接有必要说明下,在允许函数嵌套定义的语言中(很明显,C语言不允许),过程活动记录需要一个 指向它外层函数活动记录的指针,这个指针就叫静态链接,它允许内层过程访问外层过程的活动记录,因此也可以访问外层过程的局部变量。(不知C++\JAVA设计的lambda表达式和python中的函数柯西化是不是用这个原理搞出来,了解的兄弟指点一二)

    下面一张图能够清晰的解释程序运行时到底在内存上干了啥:


                                                    4、函数被调用时创建过程活动记录

    说到了过程活动记录,就不得不说setjmp\longjmp这两个函数,顾名思义,这两个函数跟代码跳转有关,有的同学会想到goto,但是goto语句只能在函数内部跳转,setjmp和longjmp却能在整个代码空间中跳转。setjmp用于设定要跳转回来的位置,longjmp则是真正执行跳转动作的函数,跳转回之前setjmp的地方。这个东东的主要作用是用来做段违规信号处理,也就是C++ 中引申出来异常捕获catch  throw。


猜你喜欢

转载自blog.csdn.net/fang_chuan/article/details/80158438