当前位置: 首页 > news >正文

内存五区的概念,内存池技术的诞生。

首先提出一道经典的面试题来引出今天的主角:

进程的虚拟空间分布是什么样的,全局变量放在哪里?

在数据初始化之后,全局变量放在.data
在数据未初始化时,全局变量放在.bss

内存五区

进程虚拟内存主要分为五个部分:

  • 栈区(自上而下)
  • 堆区(自下而上)
  • 全局区也叫做静态区(也就是用户栈)
  • 常量区
  • 程序代码区

在内核虚拟内存中物理内存内核代码和数据对于每一个进程都是一样的。
唯一不同的是进程相关的数据结构

在这里插入图片描述

栈区

栈区是自上而下的扩展的,是一块连续的内存空间。栈和堆总共的空间大小在一开始就被规定好了。他们都会随着程序的进行而发生变化。

栈是由系统自动分配的,速度很快,并且释放的也很快,程序员无法主动去控制栈的释放。如果在栈申请时没有剩余的空间就会出现OOM的情况。

栈主要用来存放局部变量和函数参数。比如你的递归函数,函数内部声明的变量等。

堆区

堆区是自下而上的扩展的,是一块不连续的内存空间。这一点和栈完全相反。

堆在程序启动初期会根据程序分配内存空间,并且在程序运行期间仍会继续分配。程序员是可以主动去申请堆内存的,分配方式类似于链表,申请的时候会以遍历的方式在堆中找到一块合适的内存块。然后将该内存块从空闲结点中删除掉。

存储在堆中的内存是需要程序员去手动释放掉的。如果不释放这些资源,就会导致内存一直被占用,最终变得越来越多。因此许多语言在继C/C++之后采用了垃圾回收机制。垃圾回收机制可以帮助程序员主动的释放掉不会再次使用的申请在堆内存上的变量,它可以让程序员更好的关注于业务,而不是释放资源。

注意:频繁的释放堆内存也会造成碎片化的问题,因此尽量不要频繁的创建和释放堆资源。

全局静态区

全局区主要用来存放全局变量和在编译器就能够确定的static值。因此这一块在程序编译时就已经被分配好内存空间了。

全局变量和静态变量是放在一块的。初始化的全局变量和静态变量在同一个区域内,未初始化的全局变量和静态变量在相邻的另一个区域内。

优点在于:不用主动去分配,由操作系统自动分配,速度快,因为编译期就能被确定并且不容易出错。

文字常量区

常量在统一运行被创建,常量区的内存是只读的,程序结束后由系统释放。

程序代码区

存放二进制代码的地方。

总结

进程的虚拟空间可以分为五大部分:栈、堆、全局区、常量区、程序代码区

其中栈和堆的比较重要,他们的主要区别有:

  1. 栈的地址是自上而下递减的,堆的地址是自下而上递增的。(注意虚拟空间的地址是从下到上依次递增的)
  2. 栈只能由系统控制分配和释放。而堆可以由程序员调用malloc/newAPI函数分配,并且由程序员主动的去释放资源。
  3. 栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。而堆是由语言进行实现的一个内存区。由语言中的函数进行调用释放。堆中的内存经常需要进行整理才能获得更大的内存空间。
  4. 频繁的创建和删除堆资源会产生碎片化问题,因为堆的申请方式跟栈不一样,堆是在内存空间中挑的一块合适的地方。而栈是一段连续的内存。并且栈释放的时候也是挨着释放的,因为出栈的肯定是要从栈顶出。

那么我们上述说了频繁的释放堆资源会造成碎片化的问题,而项目中又经常会用到堆资源,那有没有好的解决办法呢?

答案就是内存池技术

什么是内存池?

**内存池(Memory Pool)**是一种内存分配方式。通常我们习惯直接使用new、malloc等API申请分配内存。这样做的缺点在于:所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。

内存池诞生原因

默认内存管理函数的不足

利用默认的内存管理函数new/deletemalloc/free在堆上分配和释放内存会有一些额外的开销。

系统在接收到分配一定大小内存的请求时,首先查找内部维护的内存空闲块表,并且需要根据一定的算法(例如分配最先找到的不小于申请大小的内存块给请求者,或者分配最适于申请大小的内存块,或者分配最大空闲的内存块等)找到合适大小的空闲内存块。

如果该空闲内存块过大,还需要切割成已分配的部分和较小的空闲块。然后系统更新内存空闲块表,完成一次内存分配。类似地,在释放内存时,系统把释放的内存块重新加入到空闲内存块表中。如果有可能的话,可以把相邻的空闲块合并成较大的空闲块。

默认的内存管理函数还考虑到多线程的应用,需要在每次分配和释放内存时加锁,同样增加了开销。可见,如果应用程序频繁地在堆上分配和释放内存,则会导致性能的损失。并且会使系统中出现大量的内存碎片,降低内存的利用率。

默认的分配和释放内存算法自然也考虑了性能,然而这些内存管理算法的通用版本为了应付更复杂、更广泛的情况,需要做更多的额外工作。而对于某一个具体的应用程序来说,适合自身特定的内存分配释放模式的自定义内存池则可以获得更好的性能。

内存池的分类

应用程序自定义的内存池根据不同的适用场景又分为不同的类型。

线程安全的角度上来看,内存池可以分为单线程内存池多线程内存池

  • 单线程内存池整个生命周期只被一个线程使用,无需考虑互斥访问的情况。

  • 多线程内存池需要被多个线程共享,因此在每次分配和释放内存时都需要加锁

相对而言,单线程内存池性能更好,多线程内存池适用范围更广。

内存池有什么优点?

内存池会在你实例化对象,分配内存的时候预先给你分配一定数量大小相等的内存块。当这些内存不够使用的时候,会从内存池中分出一部分新的内存块来使用。如果内存块也不够的话会再申请新的内存。

这样做的显著优点就是提高了内存分配效率。

经典内存池技术

**内存池(Memory Pool)**技术因为其对内存管理有着显著的优点,在各大项目中应用广泛,备受推崇。但是,通用的内存管理机制要考虑很多复杂的具体情况,如多线程安全等,难以对算法做有效的优化,所以,在一些特殊场合,实现特定应用环境的内存池在一定程度上能够提高内存管理的效率。

经典的内存池(Memory Pool)技术,是一种用于分配大量大小相同的小对象的技术。通过该技术可以极大加快内存分配/释放过程。既然针对是特定对象的内存池,所以内存池一般设置为类模板,根据不同的对象来进行实例化。

经典内存池如何实现?

  1. 先申请一块连续的内存空间,该段内存空间能够容纳一定数量的对象。
  2. 每个对象连同一个指向下一个对象的指针一起构成一个内存节点(Memory Node)。各个空闲的内存节点通过指针来形成一个链表,链表的每一个内存节点都是一块可供分配的内存空间。
  3. 某个内存节点一旦分配出去,就将从链表中去除。
  4. 一旦释放了某个内存节点的空间,又将该节点重新加入自由内存节点链表。
  5. 如果一个内存块的所有内存节点分配完毕,若程序继续申请新的对象空间,则会再次申请一个内存块来容纳新的对象。新申请的内存块会加入内存块链表中。

参考资料

进程虚拟空间分布 - Jeff的技术栈 - 博客园 (cnblogs.com)

内存池介绍与经典内存池的实现 - 腾讯云开发者社区-腾讯云 (tencent.com)

相关文章:

内存五区的概念,内存池技术的诞生。

首先提出一道经典的面试题来引出今天的主角: 进程的虚拟空间分布是什么样的,全局变量放在哪里? 在数据初始化之后,全局变量放在.data段 在数据未初始化时,全局变量放在.bss段 内存五区 进程虚拟内存主要分为五个部分…...

力扣:字符串中的第一个唯一字符(C++实现)

题目部分: 解题思路: 方案一: 首先认真审题的小伙伴们一定会发现就是题目给了提示只包含小写字母,也就是说我们的排查范围是小写的26个字母。为了怕有的友友们一时短路想不起来,我就其按照顺序列出来吧。 即&#x…...

攻防世界 favorite_number mfw、[BJDCTF2020]ZJCTF,不过如此

favorite_number 进入环境得到源码 <?php //php5.5.9 $stuff $_POST["stuff"]; $array [admin, user]; if($stuff $array && $stuff[0] ! admin) {$num $_POST["num"];if (preg_match("/^\d$/im",$num)){if (!preg_match("…...

SummingMergeTree

假设有这样⼀种查询需求&#xff1a;终端⽤户只需要查询数据的汇总结果&#xff0c;不关⼼明细数据&#xff0c;并且数据的汇总条件是预先明确的&#xff08;GROUP BY 条件明确&#xff0c;且不会随意改变&#xff09;。 对于这样的查询场景&#xff0c;在ClickHouse中如何解决…...

JUC并发编程基础篇第一章之进程/并发/异步的概念[理解基本概念]

1. 进程和线程的概念 进程: 系统正在运行的一个应用程序;程序一旦运行就是一个进程;进程是资源分配的最小单位 线程: 是进程的实际运行单位;一个人进程可以并发控制多个线程,每条线程并行执行不同的任务 区别: 进程基本上相互独立的;而线程存在于进程内&#xff0c;是进程…...

c语言—指针进阶

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…...

总结二分法

杨辉三角形&#xff08;快速查找唯一值,mid型) //二分法解//流程&#xff1a;最大列->起点行->2k--n之间究竟哪一行&#xff08;二分排列组合&#xff09;->找到行数就等差数列对应位置#include<stdio.h> #include<stdlib.h>//注意排列组合的规律是建立在…...

二叉搜索树和AVL树

目录 一、二叉搜索树 1.什么是二叉搜索树 2.二叉搜索树的实现 &#xff08;1&#xff09;构建类 &#xff08;2&#xff09;查找函数 &#xff08;3&#xff09;插入函数 &#xff08;4&#xff09;删除函数 &#xff08;5&#xff09;补齐默认成员函数 &#xff08;6…...

计算机体系结构量化研究方法【2】高速缓存Cache

目录1.计算机存储层次结构2.缓存相关概念3.缓存组织方式4.Cache回写机制5.Cache性能量化1.计算机存储层次结构 计算机存储层次结构可以看作是一个金字塔&#xff0c;越靠上层&#xff0c;容量越小&#xff0c;速度越快 L0&#xff1a;寄存器----CPU的寄存器保存着Cache取出的…...

初识设计模式 - 迭代器模式

简介 迭代器设计模式&#xff08;Iterator Design Pattern&#xff09;&#xff0c;也叫作游标设计模式&#xff08;Cursor Design Pattern&#xff09;。 迭代器模式将集合对象的遍历操作从集合类中拆分出来&#xff0c;放到迭代器类中&#xff0c;让两者的职责更加单一。 …...

三路快排(基于三指针单趟排序的快速排序)+快排时间复杂度再分析

目录 一.前言 二. 三路快排 &#x1f60d;算法思想: &#x1f60d;算法实现步骤: &#x1f60d;三指针单趟排序的实现:​ &#x1f60d;非递归快排完全体: &#x1f914;与C标准库里的快排进行对比测试: 三.快排时间复杂度再分析 一.前言 http://t.csdn.cn/mz8dghttp://…...

Eyeshot Ultimate 2023 Crack

Eyeshot Ultimate 2023 Crack 已经引入了文档类。 工作区。文档现在包含绘制场景内容所需的所有数据。 2022版GEntities已被删除。 最后&#xff0c;一个真正的跨平台中立核心产品是可用的。 新功能 曲线、平面、曲面和体积网格。 屏幕空间环境光遮挡。 托管ReadDWG和ReadDXF类…...

JAVA-8-[SpringBoot]入门程序案例和原理分析

Spring Boot框架入门教程&#xff08;快速学习版&#xff09; Spring Boot教程BooTWiki.COM 1 Spring Boot Spring Boot是Pivotal(关键性的)团队在Spring的基础上提供的一套全新的开源框架&#xff0c;其目的是为了简化Spring应用的搭建和开发过程。Spring Boot去除了大量的X…...

前端工程化

一、AST &#xff08;抽象语法树&#xff0c;Abstract Syntax Tree&#xff09; 手把手带你走进Babel的编译世界 - 掘金 (juejin.cn) 1、概念 我们所写的代码转换为机器能识别的一种树形结构&#xff0c;本身是由一堆节点&#xff08;Node&#xff09;组成&#xff0c;每个节…...

【redis】单线程 VS 多线程(入门)

【redis】单线程 VS 多线程&#xff08;入门&#xff09; 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#…...

2023蓝桥杯Java研究生组赛题

蓝桥杯Java研究生组、JavaA组看过来&#xff0c;这两个组别题目基本一样 第一次参加了Java研究生组&#xff0c;Java组应该没有C/C那么卷吧&#xff0c;主要是觉得Java组可以避开很多ACM大佬&#xff0c;前面几题感觉难度还行没有特别难&#xff0c;后面几个大题依旧是没法做&a…...

多维时序 | MATLAB实现CNN-BiLSTM-Attention多变量时间序列预测

多维时序 | MATLAB实现CNN-BiLSTM-Attention多变量时间序列预测 目录多维时序 | MATLAB实现CNN-BiLSTM-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料预测效果 基本介绍 MATLAB实现CNN-BiLSTM-Attention多变量时间序列预测&#xff0c;CNN-BiLSTM-Atte…...

微积分——Rolle定理的理解(罗尔定理)

极值定理(Extreme Value Theorem)指出&#xff0c;闭区间[a,b]上连续的函数既有最大值&#xff0c;也有最小值。然而&#xff0c;其最大最小值都可能发生在端点。罗尔定理(Rolle’s Theorem)以法国数学家Michel Rolle(1652-1719)的名字命名&#xff0c;它给出了极值存在于闭区间…...

linux内核之select/poll/epoll

一些主流应用IO多路复用技术&#xff0c;突破高并发问题&#xff0c;如nginx、redis、netty&#xff0c;分布式服务框架dubbo&#xff0c;大数据组件hadoop、spark、flink、hbase纷纷使用netty作为网络通信组件。 一、背景&#xff1a;C10K问题 The C10K problem 最早被Dan …...

文件流下载

文件下载 后端传给前端json数据流,前端拿到之后存放在自定义的文件中import axios from "axios"; import qs from "query-string"; import {Notification } from "@arco-design/web-vue"; // 接口中需要含有文件名fileName export function dow…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...