内存五大区

1,025 阅读4分钟
  • 内存五大区图解

    内存五大区.jpg 首先系统会加载二进制代码到内存中,然后加载常量区中的常量,接着加载全局区和静态区(初始化过的静态区和没有初始化过的静态区是分开的),之后程序会找main入口函数开始执行代码,在执行代码的过程中,会创建对象和一些局部变量,其中对象存放在堆中,变量存放在栈上,以上五个区中只有堆是由程序员自己创建和销毁,而其他四个都是系统自己管理。所以从低地址到高地址的的内存区域分别是代码区、常量区、全局区、堆区和栈区。
  • 内存五大区域详细解释

    • 栈区用来存放局部变量,先进后出,一旦出了作用域就会被销毁。程序员不需要管理栈区变量的内存。栈区变量的大小是由上到下分配的,所以先声明的变量地址比后声明的变量地址要大。栈区存储在应用程序允许的内存空间的最上面。

      栈是向低地址扩展的数据结构,是一块连续的内存的区域。是栈顶的地址和栈的最大容量是系统预先规定好的,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数 ) ,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

      存储每一个函数在执行的时候都会向操作系统索要资源,栈区就是函数运行时的内存,栈区中的变量由编译器负责分配和释放,内存随着函数的运行分配,随着函数的结束而释放,由系统自动完成。(函数的调用是在栈中完成的)这块也可以叫做函数帧,从这里也可以引申出另外一个名词叫做栈帧

      栈帧:是指函数(运行中且未完成)占用的一块独立的连续内存区域 image.png

      • 优点:内存是由系统释放和分配的
      • 缺点:内存大小有限制、数据不灵活
    • 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收(一般释放后对应的指针应该指向NULL如果没有指向NULL就会出现野指针)。注意它与数据结构中的堆是两回事,分配方式类似于链表。堆区的变量地址是由下往上分配的,所以在同一线程中先声明的变量地址要比后声明的变量地址小。

      堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

      堆在系统中的申请流程:

      1. 系统中是存在一个链表的里面记载着空闲地址
      2. 让有申请内存的指令的时候系统会从空闲遍历找到(从小到大遍历)第一个空间大于申请空间的堆结点,然后将该结点从空闲链表中删除然后再分配给申请对象
      3. 由于申请的空间并非刚好等于分配空间的大小,多疑剩余的空间还是会返回到空闲链表中

      优缺点:

      • 优点:灵活方便,数据适应面广泛
      • 缺点:需要程序员手动释放、申请内存

      代码验证 image.png

    • 全局区

      全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后有系统释放

      注意:全局变量和静态变量还是少用,全局变量和静态变量的生命周期是存在整个程序的,所以大量的使用全局变量和静态变量运行内存会增加

      image.png

    • 常量区

      常量区用来存放常量字符串等,程序结束后由系统释放

      image.png 字符串常量因为可能在程序中被多次使用,所以在程序运行之前就会提前分配内存且生命周期同程序的生命周期

    • 代码区

      存放函数的二进制代码

  • 总结

    image.png