6.28 内存分配/管理 学习总结

news2024/11/16 21:47:44

一、通过程序验证系统内存分配机制

1、实验:

两个char 指针,连续先后在内存中各申请100、102个字节, 它们实际上会占用多少字节的内存空间?

如果两个char 指针,连续先后在内存中各申请200个字节, 它们实际上会占用多少字节的内存空间?

2、程序以及运行结果:

#include<iostream>
#include <unistd.h>
#include <malloc.h>
using namespace std;

int main(){
    char* p1 = (char *)malloc(100);
    char* p2 = (char *)malloc(102);
    cout << malloc_usable_size(p1) << endl;
    cout << malloc_usable_size(p2) << endl; 
    cout << static_cast<void *>(p1) << endl;   
    cout << static_cast<void *>(p2) << endl;  
    free(p1);
    free(p2);
    return 0;
}

运行出的两个指针的实际占用大小都是104字节。

通过进一步的实验发现分配的内存大小和实际占用内存有如下关系:

分配的内存大小实际占用内存大小
0 ~ 2424
25 ~ 4040
41 ~ 5656
......
89~104104
......
#include<iostream>
#include <unistd.h>
#include <malloc.h>
using namespace std;

int main(){
    char* p1 = (char *)malloc(200); 
    printf("p1 = %p\n", p1);
    char* p2 = (char *)malloc(200); 
    printf("p2 = %p\n", p2);

    printf("p1内存起始地址:%x\n", p1);
    printf("p2内存起始地址:%x\n", p2);

    printf("使用cat /proc/%d/maps查看内存分配\n",getpid()); 
    getchar();

    free(p1);
    p1 = NULL;
    free(p2);
    p2 = NULL;
    return 0;
}

实际上,除了200字节的可用空间外,还需要耗费内存控制块的空间。malloc 返回给用户态的内存起始地址比进程的多了 16 字节。这个多出来的 16 字节就是保存了该内存块的描述信息。

3、实验结果分析

        通过上述实验结果可以得出,在64位系统下,我们申请的可用内存的大小会是16x + 8,分配的内存大小在每个区间内会对应相同的一个实际占用内存大小。那么这样内存分配的目的是什么呢?通过查阅相关资料得出,这样做是为了使得内存对齐,从而提升效率。除了可用空间外,还需要耗费内存控制块的空间。所以malloc实际分配的内存大小会大于我们所需要的大小,并且由字节对齐和内存控制块两方面决定。

二、内存对齐

1、前言

        内存用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。内存是外存和CPU进行沟通的桥梁,是计算机中非常重要的组成部分。

        执行一个程序时,先由输入设备向CPU发出操作指令,CPU接收到操作指令后,硬盘中对应的程序就会被直接加载到内存中。然后,CPU 再对内存进行寻址操作,把加载到内存中的指令翻译出来,发送操作信号给操作控制器,实现程序的运行。计算机中程序的运行都是在内存中进行,所以内存的性能的好坏会影响计算机的性能。

2、内存对齐是什么?为什么要进行内存对齐?

        内存对齐就是把各种类型数据按照一定的规则在空间上排列,而不是按照顺序一个接一个的排放,这种就称为内存对齐,内存对齐是指首地址对齐。原因如下:

(1)性能方面考虑:

       CPU每次访问内存是以字长为单位访问的,所以应该内存对齐。如果访问未对齐的存,CPU需要进行两次访问操作。 因此,内存对齐可以提升性能。

        从硬件角度分析,因为内存条就是这么设计的,内存颗粒chip里的bank是并行的。一个内存是由许多chip组成,而每个chip内部是由8个bank组成。bank也就是一个二维矩阵,矩阵里的一个元素保存一个字节。

        在应用程序中,内存中连续的8个字节看似是连续的,但是在物理上并不是连续的,这是由于8个bank实际上是可以并行工作的。内存对其的情况下,工作一次,把得到的数据拼起来,就能得到内存中地址连续的8个字节,从而提高了IO效率。

(2)平台方面考虑:

        有些硬件平台上的CPU可以访问任意地址上的任意数据的,但有些只能在特定地址访问数据,否则会抛出硬件异常。因为不同的硬件平台具有一定的差别,因此,在编译阶段,把分配的内存对齐,就具有了可移植性了。

3、如果内存不对齐,会发生什么?

        未对齐的内存访问在不同的体系结构中会有不同的效果:有些计算机可以透明地处理未对齐访问,但会大大降低效率;有一些计算机可能会产生异常,并且可用调用一个异常处理程序改正;但有些计算机产生异常,但是不能校正错误;还有一些计算机没有办法处理未对齐访问,而直接读取不正确的内存地址,导致代码漏洞,并且难以发现。

三、内存管理

1、malloc

        malloc申请内存的时候,分配的是虚拟内存,会有两种方法向操作系统申请内存:

(1)通过brk()系统调用从堆分配内存

(2)通过mmap()系统调用在文件映射区分配内存

        malloc() 源码里默认定义了一个阈值:(不同的 glibc 版本定义的阈值也是不同的)

  • 如果用户分配的内存小于 128 KB,则通过 brk() 申请内存;

  • 如果用户分配的内存大于 128 KB,则通过 mmap() 申请内存;

        malloc 函数的实质有一个将可用的内存块连接为一个链表的空闲链表,有时候也用双向链表实现。每一个内存块都有一个首部称为内存控制块mem_control_block,该MCB中记录了该内存块的一些信息,例如下一个分配块的指针、当前分配块的长度、当前分配块是否可用。

typedef struct mem_control_block
{
    size_t size;  //本块大小
    bool free;  //空闲状态
    struct mem_control_block *next;  //后块指针
}MCB;
MCB *g_top = NULL;  //栈顶指针

        malloc分配时会去搜索空闲链表,为了保证分配给程序的内存的连续性,根据内存匹配原则,找到一个能满足所需空间的空闲内存块,然后把该部分空间分配出去,并且返回这部分空间的起始指针。malloc返回的指针是可用空间的起始指针,也就是跟在首部后面的地址,上述分配块的首部对于程序是不可见的。如果不能找到满足条件的内存块,就会向操作系统申请扩展堆内存,操作系统会分配新的足量内存并将其控制块压入链表栈。

        这相当于用到了池化技术,实现了一个内存池。先向操作系统申请了适当内存空间,然后自己进行管理。如果不够满足实际需求,再向操作系统申请。不需要每次malloc都进行系统调用,那样开销比较大,会影响系统的性能。

        系统函数brk()和sbrk()被用来调节分配给进程的数据段的内存量。 brk和sbrk底层维护了一个堆上的指针,以增量的方式管理动态内存(堆)。通常,这些函数是由一个更大的内存管理库函数(如malloc)调用的。sbrk(x) 函数,x是申请空间大小,0不申请空间,大于0申请空间,小于0 释放空间。而brk(addr),需要将堆顶指针向后移动到哪个地址addr。移动的空间大小,就是申请的空间大小。

2、free

    free会将内存块重新插入到空闲链表中,并且修改内存头部的空闲状态。free只接受一个指针,却可以释放恰当大小的内存,这是因为在分配的区域的首部保存了该区域的大小。

        malloc 申请内存的时候,会有两种方式向操作系统申请堆内存:1、通过 brk() 系统调用从堆分配内存;2、通过 mmap() 系统调用在文件映射区域分配内存。采用第一种方式申请的内存,堆内存还存在,没有归还给操作系统,而是放回内存池里;采用第二种方式申请的内存会归还给操作系统。

参考文章:

详解内存对齐_Sunshine-松的博客-CSDN博客

带你深入理解内存对齐最底层原理 - 知乎

内存管理(六):一文搞懂malloc、free实现原理 - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/700651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

青大数据结构【2017】【综合应用、算法分析】

关键字&#xff1a; 平衡二叉树、平均查找长度、单链表、二叉树中序遍历非递归 三、综合应用 平衡二叉树AVL定义&#xff1a;任意节点的子树的高度差都小于等于 1 ASL&#xff08;12*24*3&#xff09;/717/7 四、算法分析

APA 参考页格式 | 第六版指南

参考页&#xff1a;文章最后列出所有的参考文献的页面。引用&#xff1a;指在文章正文中进行引用。 APA 参考页是论文末尾的一个单独页面&#xff0c;其中列出了您在正文中引用的所有来源。参考文献按字母顺序排序&#xff0c;双倍行距&#xff0c;并使用1/2 英寸的悬挂缩进进行…

接口自动化测试中,文件上传该如何测试?

在服务端自动化测试过程中&#xff0c;文件上传类型的接口对应的请求头中的 content-type 为 multipart/form-data; boundary...&#xff0c;碰到这种类型的接口&#xff0c;使用 Java 的 REST Assured 或者 Python 的 Requests 均可解决。 实战练习 Python 版本 在 Python …

初识Go语言24-数据结构与算法【链表、栈】

文章目录 数据结构与算法链表栈 数据结构与算法 链表 ---手写单链表 type Node struct {Info intNext *Node }type List struct {Head *NodeLen intTail *Node }func (list *List) Add(ele int) {node : &Node{Info: ele, Next: nil}if list.Len 0 {list.Head nodelist…

基于WebSocket的简易聊天室的基本实现梳理

一&#xff0c;前言 目前在很多网站为了实现推送技术所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔&#xff08;如每1秒&#xff09;&#xff0c;由浏览器对服务器发出HTTP请求&#xff0c;然后由服务器返回最新的数据给客户端的浏览器。HTTP 协议是一种无状态的、无连…

轨道交通车体自动化检修测量大尺寸测量仪器-CASAIM激光三维扫描仪

现今我国轨道交通高速发展&#xff0c;重大装备技术的进步离不开先进的大尺寸测量手段支持&#xff0c;CASAIM大尺寸测量在测量环境、测量精度和测量效率上明显区别于常规尺寸测量&#xff0c;可以快速检测车体表面的尺寸变形等问题&#xff0c;实现高精度、高效率的自动化车体…

(质数)牛客·Prime Distance

非质数的一个性质&#xff1a; 必定有一个因子大于它的算术平方根。 该性质有范围限制&#xff0c;一般情况下都可以使用。以后数学家们再扩张。碰到质数的一般做法&#xff1a;假定范围为[1,n] 1、预处理1-√n的质数&#xff0c;存入数组p中 2、对于[1-n]里的数&#xff0c;用…

git常用命令之Push

9. Push 命令作用延展阅读git push --set-upstream origin releasegit push -u origin release 为缩写版本1. .git/config配置文件会追加如下关联关系&#xff0c;[branch “release”] remote origin merge refs/heads/release故后续可以直接执行git push2. .git\refs\remo…

VueCli的Nuxt重构

我的博客用vuecli写的&#xff0c;SEO不忍直视。于是用Nuxt重构了代码&#xff0c;过程中踩了无数坑 一&#xff1a;body样式不生效 正常的body样式设置不能生效&#xff0c;需要在nuxt.config.js中配置 1、设置bodyAttrs的class属性&#xff0c;该属性值对应一个类名 2、该…

【Java面试题】Java基础——查找算法

文章目录 基本查找二分查找★★★插值查找斐波那契查找分块查找 基本查找 基本查找也叫做顺序查找 ​ 说明&#xff1a;顺序查找适合于存储结构为数组或者链表。 基本思想&#xff1a;顺序查找也称为线形查找&#xff0c;属于无序查找算法。从数据结构线的一端开始&#xff…

IP地址定位查询技术,不管对方在哪,轻轻松松查到他的位置

这是外面在卖588的抓ip技术&#xff0c;真的很简单&#xff0c;卖此技术的人帮人查一次都能赚几十&#xff0c;每天都能出个两三单 玩法&#xff1a;可以生成链接、邮件、图片、pdf的形式&#xff0c;发送给对方的微信或者QQ等地方&#xff0c;只要对方点击后&#xff0c;立马…

知易行难!项目推进的6大常见问题

项目推进是一项企业发展业务中的关键任务。然而&#xff0c;许多项目在实施过程中遇到各种困难和挑战&#xff0c;导致项目无法按计划进行或无法实现预期的成果。以下是项目推进过程中常见的六个问题以及解决方案。1、项目目标不明确 项目推进时&#xff0c;如果项目团队不清楚…

Material —— 材质节点 | Utility

目录 AddNamedRerouteDeclarationNode... AddRerouteNode... AntialiasedTextureMask AtmosphereSunLightIlluminanceOnGround AtmosphereSunLightVector BentNormalCustomOutput BlackBody BoxMask-2D BoxMask-3D BumpOffset&#xff08;B&#xff09; ChannelMask…

Spring Boot 中的 STOMP 是什么,原理,如何使用

Spring Boot 中的 STOMP 是什么&#xff0c;原理&#xff0c;如何使用 介绍 在 Spring Boot 中&#xff0c;STOMP 是一种简单的文本协议&#xff0c;用于在客户端和服务器之间进行实时消息传递。它是 WebSocket 协议的一种扩展&#xff0c;可以在 WebSocket 上运行。在本文中…

Electron + ts + vue3 + vite 项目搭建

新建一个vite ts vue3的项目 在创建选项中选择ts和vue选项。 之后&#xff0c;安装依赖之后试运行一下&#xff0c;出现一下页面意味着vite-vue项目创建成功。 npm create vitelatest electron-vue3-ts-vite-test1 VSCode打开electron-vue3-ts-vite-test1或者cd electron-…

vue项目运行后使用ip地址在手机上打开

文章目录 1、获取ip地址2、保证你的手机和电脑使用的是一个wifi3、修改配置文件 1、获取ip地址 windowr&#xff0c;输入cmd按回车后在输入ipconfig ipv4地址就是你了 2、保证你的手机和电脑使用的是一个wifi 3、修改配置文件 &#xff08;1&#xff09;vue.config.js文件中…

大数据时代,商业智能BI的使用规则

商业智能BI的火热程度让很多不了解的企业也在内部部署了BI系统&#xff0c;怎么利用BI创造价值也就成了新的问题。 商业智能面向管理人员 很多人其实不理解&#xff0c;为什么说企业的管理人员想要完全了解企业的各项业务发展情况实际上是很困难的。 一家企业有这么多部门&a…

【redis】stream消息队列

目录 截图一、代码示例1.1 pom.xml依赖1.2 application.xml配置1.3 启动类1.4 配置类1.5 消息实体1.6 自定义错误1.7 自定义注解1.8 服务类1.9 监听类1.10 controller 截图 一、代码示例 1.1 pom.xml依赖 <?xml version"1.0" encoding"UTF-8"?> …

Unity VR:XR Interaction Toolkit 官方 Demo

Unity XR Interaction Toolkit 提供了一个官方 Demo&#xff0c;包含了丰富的功能演示&#xff0c;可以供大家更好地学习 VR 开发。 项目地址&#xff1a;https://github.com/Unity-Technologies/XR-Interaction-Toolkit-Examples 项目里包括多个演示场景&#xff0c;而 XRI_…

Unity 中 TextMeshPro 字体位置偏上/偏下

问题&#xff1a;在Unity中创建了一个新的TextMeshPro 字体&#xff0c;在使用的时候布局设置的居中对齐&#xff0c;但在场景中实际位置却和预期位置不服&#xff0c;如下图。 当然通过调整布局设置&#xff0c;也可以显示成正常的效果&#xff0c;但不可能所有文本都通过这…