C++之内存模型(内存区域)

1.C++五种存储区域:

1.1 堆

  • 定义:在内存管理的语境下,指的是动态分配内存的区域。这个堆跟数据结构里的堆不是一回事。这里的内存,被分配之后需要手工释放,否则,就会造成内存泄漏。
  • C++ 标准里一个相关概念是自由存储区,英文是 free store,特指使用 new和 delete来分配和释放内存的区域。一般而言,这是堆的一个子集。new和 delete操作的区域是 free store,malloc和free操作的区域是 heap,但 new和 delete 通常底层使用malloc和 free来实现,所以free store也是heap。
  • 堆通常进行的操作:让内存管理器分配一个某个大小的内存块,让内存管理器释放一个之前分配的内存块。
  • 生长方向:对于堆来说,生长方向是向上的,也就是说向着内存地址增加的方向。

1.2 栈

  • 定义:在内存管理的语境下,指的是函数调用过程中产生的局部变量函数形参的区域。这个栈和数据结构里的栈高度相似,都满足“后进先出”的规则。
  • 栈通常进行的操作:

1)栈上的分配极为简单,移动一下栈指针而已。
2)栈上的释放也极为简单,函数执行结束时移动一下栈指针即可。
3)由于后进先出的执行过程,不可能出现内存碎片。

  • 执行效率:栈区的执行效率高于堆区。
  • 生长方向:对于栈来说,生长方向是向下的,也就是说向着内存地址减小的方向。
  • 函数调用参数入栈顺序:参数的入栈顺序一般是从右向左
  • 指针存放的位置:指针不管指向任何类型,指针自身的位置只可能在栈区和全局静态区,函数内定义(包括形参)在栈区,函数外定义在全局静态区。

1.3 全局静态区

  • 定义:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区,程序结束释放。

1.4 代码区

  • 定义:存放函数体等二进制代码;

1.5 常量区

  • 定义:这是一块比较特殊的存储区,他们里面存放的是const,不允许修改。

2.malloc、calloc、realloc底层实现原理

2.1 malloc底层实现原理

2.1.1 malloc分配简单结论

  • 当开辟的空间小于128K时,调用sbrk函数,malloc的底层实现是系统调用函数brk,其主要移动指针 _enddata(此时的 _enddata指的是Linux地址空间中堆段的末尾地址,不是数据段的末尾地址)。
  • 当开辟的空间大于128K时,mmap系统调用函数来在文件映射区域找一块空间来开辟。
  • 这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。

2.1.2 malloc分配详细过程

2.1.2.1 malloc小于128K的内存,使用brk分配
  • 将_enddata往高地址推(只分配虚拟空间,不对应物理内存,因为没有初始化),第一次读/写数据时,引起内核缺页中断,内核才分配对应的物理内存,然后虚拟地址空间建立映射关系。
  • 当malloc(30K)的时候,malloc函数会调用brk系统调用,将_enddata指针往高地址推30K,就完成虚拟内存分配。事实是:_endata+30K只是完成虚拟地址的分配,这块内存现在还是没有物理页与之对应的,等到进程第一次读写A这块内存的时候,发生缺页中断,这个时候,内核才分配A这块内存对应的物理页。也就是说,如果用malloc分配这块内容,然后从来不访问它,那么对应的物理页是不会被分配的。
  • 如下图所示:当进程调用free(B),B对应的虚拟内存和物理内存都没有释放,因为只有一个_endata指针,如果往回推,那么D这块内存怎么办呢?当然,B这块内存,是可以重用,如果这个时候再来一个40K的请求,那么malloc很可能就把B这块内存返回回去。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM(Java虚拟机)内存模型是用于管理Java程序运行时内存的规范。它定义了JVM如何组织和访问内存,以及如何在运行时执行Java程序。 JVM内存模型主要分为以下几个部分: 1. 堆(Heap):用于存储对象实例和数组。堆是Java程序运行时的动态数据区域,所有的对象实例和数组都在堆上分配内存。 2. 方法区(Method Area):用于存储类的信息、常量、静态变量等。方法区是被所有线程共享的内存区域,它包含加载的类信息、常量池、静态变量、即时编译器编译后的代码等。 3. 栈(Stack):用于存储线程执行方法的局部变量、操作数栈、方法调用等信息。每个线程在执行方法时,都会创建一个对应的栈帧,栈帧中包含了局部变量表、操作数栈、动态链接、方法返回地址等信息。 4. 本地方法栈(Native Method Stack):用于执行本地方法的栈。与栈类似,但是本地方法栈中存储的是本地方法(如使用C或C++编写的方法)的信息。 5. 程序计数器(Program Counter Register):用于指示当前线程执行的字节码指令地址。每个线程都有一个独立的程序计数器,用于记录当前线程执行的位置。 除了这些主要的内存区域之外,JVM还有一些其他的辅助内存区域,如直接内存(Direct Memory)用于NIO操作中的缓冲区分配,以及JVM自身使用的一些内存空间。 JVM内存模型的设计旨在提供高效的内存管理和线程间的数据共享,并且对于Java程序员来说,不需要手动管理内存,JVM会自动进行垃圾回收等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值