码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-04-29 15:06:38      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:

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

对于一个源文件,哪些地方会放到哪个段,如下图:
技术分享

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

而对于一个可执行程序,它的段在内存分布(进程的地址空间)如下:
技术分享

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

通过编写程序加深理解:

#include <stdio.h>

#define ARRAY_SUM 50

char 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语言是不允许函数在函数内部定义的,所以它的活动记录中不需要静态链接。

下面是每个函数调用在运行时创建过程活动记录的过程:
技术分享

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

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

标签:

原文地址:http://blog.csdn.net/talent_cyj/article/details/51276832

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!