关于程序运行时的数据结构

来源:互联网 发布:淘宝宝贝突然被删除 编辑:程序博客网 时间:2024/06/05 15:26

对于可执行文件,它包含了许多的段,例如(数据段,文本段,BSS段等),它们是二进制文件中简单的区域,里面保存了和某种特定类型(如符号表条目)相关的所有信息。

对于一个源文件,哪些地方会放到哪个段,如下图:
这里写图片描述

可得知,程序代码是存放在文本段,初始化的全局变量和静态变量是存放到数据段中的,而没有初始化的全局变量和静态变量则是存放到BSS,运行时所需要的BSS段的大小记录在目标文件中,但BSS段并不占据目标文件的任何空间,局部变量、临时数据、传递到函数中的参数则是存储于栈中,而通过函数调用malloc动态分配的内存则是在堆中。对于数组的初始化,初始化所用的数据则是放在只读数据段。const修饰的变量也是存放在只读数据段。

而对于一个可执行程序,它的段在内存分布(进程的地址空间)如下:
这里写图片描述

在上图中,注意虚拟地址空间的最低部分未被映射,它位于进程的地址空间内,但并未赋予物理地址,所以任何对它的引用都是非法的,该段空间用于捕捉使用空指针和小整型值的指针引用内存的情况。

通过编写程序加深理解:

#include <stdio.h>#define ARRAY_SUM 50char global_var_data = 'A';   //存放在数据段 char global_var_bss;          //存放在BSS段 int main(void){    static char static_var_data = 'A';   //存放在数据段    static char static_var_bss;          //存放在BSS段    char stack_var_char;    //存放在栈中    char rodata_var_array_char[ARRAY_SUM] = "I AM IN RODATA";   //数组变量stack_var_array位于栈,但字符串常量则位于只读数据段    int  rodata_var_array_int[ARRAY_SUM] = {1, 2, 3, 4};        //常量1,2,3,4,0,0...这些都存储在只读数据段    int *heap_var_int = malloc(100);    //存放在堆中     char *heap_var_char = malloc(100);  //存放在堆中     printf ("global_var_data        = %p   存放在数据段\n", &global_var_data);         printf ("static_var_data        = %p   存放在数据段\n", &static_var_data);    printf ("global_var_bss         = %p   存放在BSS段\n", &global_var_bss);        printf ("static_var_bss         = %p   存放在BSS段\n", &static_var_bss);    printf ("heap_var_int           = %p   存放在堆中\n", heap_var_int);    printf ("heap_var_char          = %p   存放在堆中\n", heap_var_char);    printf ("stack_var_char         = %p   存放在栈中\n", &stack_var_char);    printf ("rodata_var_array_char  = %p   存放在栈中\n", rodata_var_array_char);    printf ("rodata_var_array_int   = %p   存放在栈中\n", rodata_var_array_int);    printf ("\"I AM IN RODATA\"     = %p   存放在只读数据段\n", "I AM IN RODATA");      free(heap_var_int);    free(heap_var_char);    return 0;}

运行结果打印如下:
这里写图片描述

当考虑到共享库时,进程的地址空间则变成下图所示:
这里写图片描述

在进行函数调用时,堆栈存储与此有关的一些维护性信息,这些信息称为堆栈结构,或称为过程活动记录。运行时系统维护一个指针(常常位于寄存器中),通常称为fp,用于提示活动堆栈结构。它的值是最靠近堆栈顶部的过程活动记录的地址。对于过程活动记录,它的描述可以见下图:
这里写图片描述

这里所描述的静态链接是指 指向它的外层函数的活动记录指针,它允许内层过程访问外层过程的活动记录,因此也可以访问外层过程的局部数据。但这仅限于允许函数在函数内部定义的语言当中,而C语言是不允许函数在函数内部定义的,所以它的活动记录中不需要静态链接。

下面是每个函数调用在运行时创建过程活动记录的过程:
这里写图片描述

但在某些编译器中,可能会把过程活动记录的内容放到寄存器中,这样可以提高函数调用的速度。

0 0
原创粉丝点击