内存空间布局:代码段、数据段,栈,堆 ,寄存器

首先看一段代码:

 #include <stdio.h>
  
  int glob_val;               //global uninitialized
  int glob_val2 = 2;          //global initialized
  //int glob_val5 = 4;
  //int glob_val6 = 4;
  static int glob_val3;       //static global uninitialized
  static int glob_val4 = 1;   //static global initialized
  
  int main(int argc , char *argv[]){
      int auto_val ;          //local uninitialized
      int auto_val2 = 3;      //local initialized
      static int stat_val ;   //static local uninitialized
      static int stat_val2 = 4;   //static local initialized
      char *p = "Hello World!";   //point to constant
  //  register reg_val = 5 ;      //register
  
      printf( "global uninitialized var's addr:"
              " %#08lx\n " , &glob_val );
      printf( "global initialized var's addr:"
              " %#08lx\n " , &glob_val2 );
      printf( "global initialized var's addr:"
              " %#08lx\n " , &glob_val3 );
      printf( "static global initialized var's addr:"
              " %#08lx\n " , &glob_val4 );
  
      printf( "constant value's addr:  %#08lx \n "
              "pointer's addr: %#08lx\n" , p , &p );
  //  printf( "register uninitialized var's addr:"
  //          " %#x\n " , &reg_val );
  
      printf( "local uninitialized var's addr:"
              " %#08lx\n " , &auto_val );
      printf( "local initialized var's addr:"
              " %#08lx\n " , &auto_val2 );
      printf( "static local uninitialized var's addr:"
              " %#08lx\n " , &stat_val );
      printf( "static local initialized var's addr:"
              " %#08lx\n " , &stat_val2 );
     return 0;
  }

输出的结果为:

global uninitialized var's addr: 0x601058
global initialized var's addr: 0x601040
global initialized var's addr: 0x601050
static global initialized var's addr: 0x601044
constant value's addr: 0x400698
pointer's addr: 0x7fff54c54688
local uninitialized var's addr: 0x7fff54c54680
local initialized var's addr: 0x7fff54c54684
static local uninitialized var's addr: 0x601054
static local initialized var's addr: 0x601048

然后我们再来看 APUE P164的配图 

从上面可以看出,内存大致分为几个段:

代码段(正文段):代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

BSS:BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

堆(heap:堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

从上面程序运行的结果,可以看出:

扫描二维码关注公众号,回复: 16403443 查看本文章

1.函数代码存放在代码段。声明的类如果从未使用,则在编译时,会优化掉,其成员函数不占代码段空间。
全局变量或静态变量,放在数据段,注:按理来说 ,没有声明的全局变量或静态变量应该保存在BSS中,但结果看出感觉它们在一块

局部变量放在栈中,
用new产生的对象放在堆中,

常量保存在常量区,常量区地址比数据段地址更低

CPU寄存器:CPU寄存器,其实就是来控制代码段和数据段的指令及数据读取的地方,当然,CPU也有自己存放数据的地方,那就是通用寄存器里的数据寄存器,通常是EDX寄存器,C语言里有个register,就是把数据放在这个寄存器里,这样读取数据就相当的快了,因为不用去内存找,就省去了寻址和传送数据的时间开销。他还有一些寄存器是用来指示当前代码段的位置、数据段的位置、堆栈段的位置等等(注意这里存放的只是相应的代码或数据在内存中的地址,并不是实际的值,然后根据这个地址,通过地址总线和数据总线,去内存中获取相应的值)不然在执行代码的时候,指令和数据从哪取呢?呵呵。。。他里面还有标志寄存器,用来标识一些状态位,比如标识算术溢出呀等等。。。。。

寄存器是特殊形式的内存,嵌入到处理器内部。

每个进程需要访问内存中属于自身的区域,因此,可将内存划分成小的段,按需分发给进程。
寄存器用来存储和跟踪进程当前维护的段。偏移寄存器(Offset Registers)用来跟踪关键的数据放在段中的位置。在进程被载入内存中时,基本上被分裂成许多小的节(section)。我们比较关注的是6个主要的节:

(1) .text 节
    .text 节基本上相当于二进制可执行文件的.text部分,它包含了完成程序任务的机器指令。
该节标记为只读,如果发生写操作,会造成segmentation fault。在进程最初被加载到内存中开始,该节的大小就被固定。
(2).data 节
.data节用来存储初始化过的变量,如:int a =0 ; 该节的大小在运行时固定的。
(3).bss 节
栈下节(below stack section ,即.bss)用来存储为初始化的变量,如:int a; 该节的大小在运行时固定的。
(4) 堆节
堆节(heap section)用来存储动态分配的变量,位置从内存的低地址向高地址增长。内存的分配和释放通过malloc() 和 free() 函数控制。
(5) 栈节
栈节(stack section)用来跟踪函数调用(可能是递归的),在大多数系统上从内存的高地址向低地址增长。
同时,栈这种增长方式,导致了缓冲区溢出的可能性。
(6)环境/参数节

环境/参数节(environment/arguments section)用来存储系统环境变量的一份复制文件,
进程在运行时可能需要。例如,运行中的进程,可以通过环境变量来访问路径、shell 名称、主机名等信息。
该节是可写的,因此在格式串(format string)和缓冲区溢出(buffer overflow)攻击中都可以使用该节。
另外,命令行参数也保持在该区域中.

 

另外还有一篇文章:http://www.cppblog.com/prayer/archive/2009/08/17/93594.html我去验证BSS和数据段,没有验证成功。

 


猜你喜欢

转载自blog.csdn.net/big_bit/article/details/51273063
今日推荐