首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Linux下C程序进程地址空间布局

Linux下C程序进程地址空间布局

我们在学习C程序开发时经常会遇到一些概念:代码段、数据段、BSS段(Block Started by Symbol) 、堆(heap)和栈(stack)。先看一张教材上的示意图(来源,《UNIX环境高级编程》一书),显示了进程地址空间中典型的存储区域分配情况。

从图中可以看出:

从低地址到高地址分别为:代码段、(初始化)数据段、(未初始化)数据段(BSS)、堆、栈、命令行参数和环境变量堆向高内存地址生长栈向低内存地址生长
还经常看到下面这个图(来源,不详):

先看一段程序。

    #include <stdio.h> 
  • #include <stdlib.h>  int global_init_a=1;   
  • int global_uninit_a;   static int static_global_init_a=1;   
  • static int static_global_uninit_a;   const int const_global_a=1;   
  • int global_init_b=1;   int global_uninit_b;   
  • static int static_global_init_b=1;   static int static_global_uninit_b;   
  • const int const_global_b=1; /*上面全部为全局变量,main函数中的为局部变量*/ int main()   int local_init_a=1;   
  • int local_uninit_a;   static int static_local_init_a=1;   
  • static int static_local_uninit_a;   const int const_local_a=1;   
  • int local_init_b=1;   int local_uninit_b;   
  • static int static_local_init_b=1;   static int static_local_uninit_b;   
  • const int const_local_b=1;   int * malloc_p_a;   
  • malloc_p_a=malloc(sizeof(int));   printf(" &global_init_a=%p   
  • global_init_a=%d ",&global_init_a,global_init_a);
  • printf(" &global_uninit_a=%p   global_uninit_a=%d ",&global_uninit_a,global_uninit_a);   printf(" &static_global_init_a=%p   
  • static_global_init_a=%d ",&static_global_init_a,static_global_init_a);  
  •  printf("&static_global_uninit_a=%p
  • static_global_uninit_a=%d ",&static_global_uninit_a,static_global_uninit_a);
  • printf(" &const_global_a=%p   const_global_a=%d ",&const_global_a,const_global_a);   printf(" &global_init_b=%p   
  • global_init_b=%d ",&global_init_b,global_init_b);  
  •  printf(" &global_uninit_b=%p   global_uninit_b=%d ",&global_uninit_b,global_uninit_b);  printf(" &static_global_init_b=%p   static_global_init_b=%d ",&static_global_init_b,static_global_init_b); printf("&static_global_uninit_b=%p static_global_uninit_b=%d ",&static_global_uninit_b,static_global_uninit_b);   printf(" &const_global_b=%p   
  • const_global_b=%d ",&const_global_b,const_global_b);   printf(" &local_init_a=%p   
  • local_init_a=%d ",&local_init_a,local_init_a);   printf(" &local_uninit_a=%p   
  • local_uninit_a=%d ",&local_uninit_a,local_uninit_a);  
  •  printf(" &static_local_init_a=%p
  • static_local_init_a=%d ",&static_local_init_a,static_local_init_a);   printf(" &static_local_uninit_a=%p static_local_uninit_a=%d ",&static_local_uninit_a,static_local_uninit_a);   printf(" &const_local_a=%p   
  • const_local_a=%d ",&const_local_a,const_local_a);   printf(" &local_init_b=%p   
  • local_init_b=%d ",&local_init_b,local_init_b);   printf(" &local_uninit_b=%p   
  • local_uninit_b=%d ",&local_uninit_b,local_uninit_b);
  • printf(" &static_local_init_b=%p   static_local_init_b=%d ",&static_local_init_b,static_local_init_b);    
  •  printf(" &static_local_uninit_b=%p
  • static_local_uninit_b=%d ",&static_local_uninit_b,static_local_uninit_b);  
  •  printf(" &const_local_b=%p     const_local_b=%d ",&const_local_b,const_local_b);   printf(" malloc_p_a=%p   
  • *malloc_p_a=%d ",malloc_p_a,*malloc_p_a);   
  • return 0;
下面是输出结果。

先仔细分析一下上面的输出结果,看看能得出什么结论。貌似很难分析出来什么结果。好了我们继续往下看吧。
接下来,通过查看proc文件系统下的文件,看一下这个进程的真实内存分配情况。(我们需要在程序结束前加一个死循环,不让进程结束,以便我们进一步分析)。
在return 0前,增加 while(1); 语句
重新编译后,运行程序,程序将进入死循环。

使用ps命令查看一下进程的pid

#ps -aux | grep a.out

查看/proc/2699/maps文件,这个文件显示了进程在内存空间中各个区域的分配情况。
#cat /proc/2699/maps

上面红颜色标出的几个区间是我们感兴趣的区间:

08048000-08049000 r-xp 貌似是代码段08049000-0804a000 r--p 暂时不清楚,看不出来0804a000-0804b000 rw-p 貌似为数据段08a7e000-08a9f000 rw-p 堆bff73000-bff88000 rw-p 栈
我们把这些数据与最后一次的程序运行结果进行比较,看看有什么结论。
&global_init_a=0x804a018 全局初始化:数据段 global_init_a=1
&global_uninit_a=0x804a04c 全局未初始化:数据段 global_uninit_a=0
&static_global_init_a=0x804a01c 全局静态初始化:数据段 static_global_init_a=1
&static_global_uninit_a=0x804a038 全局静态未初始化:数据段 static_global_uninit_a=0
&const_global_a=0x80487c0 全局只读变量: 代码段 const_global_a=1

&global_init_b=0x804a020 全局初始化:数据段 global_init_b=1
&global_uninit_b=0x804a048 全局未初始化:数据段 global_uninit_b=0
&static_global_init_b=0x804a024 全局静态初始化:数据段 static_global_init_b=1
&static_global_uninit_b=0x804a03c 全局静态未初始化:数据段 static_global_uninit_b=0
&const_global_b=0x80487c4 全局只读变量: 代码段 const_global_b=1

&local_init_a=0xbff8600c 局部初始化:栈 local_init_a=1
&local_uninit_a=0xbff86008 局部未初始化:栈 local_uninit_a=134514459
&static_local_init_a=0x804a028 局部静态初始化:数据段 static_local_init_a=1
&static_local_uninit_a=0x804a040 局部静态未初始化:数据段 static_local_uninit_a=0
&const_local_a=0xbff86004 局部只读变量:栈 const_local_a=1

 &local_init_b=0xbff86000 局部初始化:栈 local_init_b=1
&local_uninit_b=0xbff85ffc 局部未初始化:栈 local_uninit_b=-1074241512
 &static_local_init_b=0x804a02c 局部静态初始化:数据段 static_local_init_b=1
&static_local_uninit_b=0x804a044 局部静态未初始化:数据段 static_local_uninit_b=0
&const_local_b=0xbff85ff8 局部只读变量:栈 const_local_b=1

p_chars=0x80487c8 字符串常量:代码段 p_chars=abcdef
malloc_p_a=0x8a7e008 malloc动态分配:堆 *malloc_p_a=0
返回列表