首页 > 系统相关 >内存管理

内存管理

时间:2022-08-16 14:13:14浏览次数:62  
标签:字节 管理 int 内存 对齐 数据 CPU

内存管理

不同语言的内存管理

不同语言的内存管理方式:

  • C/C++这种内存堆空间的申请和释放完全靠自己管理

  • Java 依赖JVM来做内存管理,不了解jvm内存管理的机制,很可能会因一些错误的代码写法而导致内存泄漏或内存溢出

  • Python内存管理是由私有堆空间管理的,所有的python对象和数据结构都存储在私有堆空间中。程序员没有访问堆的权限,只有解释器才能操作。

C++的内存管理

以C++为例来介绍一下编程语言的内存管理。

如果我们写C++的程序,就要知道栈和堆的概念,程序运行时所需的内存空间分为 固定部分,和可变部分,如下:

固定部分的内存消耗 是不会随着代码运行产生变化的, 可变部分则是会产生变化的

更具体一些,一个由C/C++编译的程序占用的内存分为以下几个部分:

  • 栈区(Stack) :由编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构中的栈。

  • 堆区(Heap) :一般由程序员分配释放,若程序员不释放,程序结束时可能由OS收回

  • 未初始化数据区(Uninitialized Data): 存放未初始化的全局变量和静态变量

  • 初始化数据区(Initialized Data):存放已经初始化的全局变量和静态变量

  • 程序代码区(Text):存放函数体的二进制代码

代码区和数据区所占空间都是固定的,而且占用的空间非常小,那么看运行时消耗的内存主要看可变部分。

在可变部分中,栈区间的数据在代码块执行结束之后,系统会自动回收,而堆区间数据是需要程序员自己回收,所以也就是造成内存泄漏的发源地。

而Java、Python的话则不需要程序员去考虑内存泄漏的问题,虚拟机都做了这些事情

如何计算程序占用多大内存

想要算出自己程序会占用多少内存就一定要了解自己定义的数据类型的大小,如下:

注意图中有两个不一样的地方,为什么64位的指针就占用了8个字节,而32位的指针占用4个字节呢?

1个字节占8个比特,那么4个字节就是32个比特,可存放数据的大小为2^32,也就是4G空间的大小,即:可以寻找4G空间大小的内存地址。

大家现在使用的计算机一般都是64位了,所以编译器也都是64位的。

安装64位的操作系统的计算机内存都已经超过了4G,也就是指针大小如果还是4个字节的话,就已经不能寻址全部的内存地址,所以64位编译器使用8个字节的指针才能寻找所有的内存地址。

注意2^64是一个非常巨大的数,对于寻找地址来说已经足够用了

内存对齐

不要以为只有C/C++才会有内存对齐,只要可以跨平台的编程语言都需要做内存对齐,Java、Python都是一样的

  1. 平台原因:不是所有的硬件平台都能访问任意内存地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。为了同一个程序可以在多平台运行,需要内存对齐。
  1. 硬件原因:经过内存对齐后,CPU访问内存的速度大大提升。

可以看一下这段C++代码输出的各个数据类型大小是多少?

struct node{
   int num;
   char cha;
}st;
int main() {
    int a[100];
    char b[100];
    cout << sizeof(int) << endl;
    cout << sizeof(char) << endl;
    cout << sizeof(a) << endl;
    cout << sizeof(b) << endl;
    cout << sizeof(st) << endl;
}

看一下和自己想的结果一样么, 我们来逐一分析一下。

其输出的结果依次为:

4
1
400
100
8

此时会发现,和单纯计算字节数的话是有一些误差的。

这就是因为内存对齐的原因。

来看一下内存对齐和非内存对齐产生的效果区别。

CPU读取内存不是一次读取单个字节,而是一块一块的来读取内存,块的大小可以是2,4,8,16个字节,具体取多少个字节取决于硬件。

假设CPU把内存划分为4字节大小的块,要读取一个4字节大小的int型数据,来看一下这两种情况下CPU的工作量:

第一种就是内存对齐的情况,如图:

一字节的char占用了四个字节,空了三个字节的内存地址,int数据从地址4开始。

此时,直接将地址4,5,6,7处的四个字节数据读取到即可。

第二种是没有内存对齐的情况如图:

char型的数据和int型的数据挨在一起,该int数据从地址1开始,那么CPU想要读这个数据的话来看看需要几步操作:

因为CPU是四个字节四个字节来寻址,首先CPU读取0,1,2,3处的四个字节数据

CPU读取4,5,6,7处的四个字节数据

合并地址1,2,3,4处四个字节的数据才是本次操作需要的int数据

此时一共需要两次寻址,一次合并的操作。

大家可能会发现内存对齐岂不是浪费的内存资源么?

是这样的,但事实上,相对来说计算机内存资源一般都是充足的,我们更希望的是提高运行速度。

编译器一般都会做内存对齐的优化操作,也就是说当考虑程序真正占用的内存大小的时候,也需要认识到内存对齐的影响。

标签:字节,管理,int,内存,对齐,数据,CPU
From: https://www.cnblogs.com/01black-white/p/16591344.html

相关文章

  • 100行代码实现一个RISC-V架构下的多线程管理框架
    1.摘要本文将基于RISC-V架构和qemu仿真器实现一个简单的多线程调度和管理框架,旨在通过简单的代码阐明如何实现线程的上下文保存和切换,线程的调度并非本文的重点,故......
  • 按照webpack教程起步自己写的理解 webpack起步 + 管理输出+开发环境设置
    一、webpack起步默认打包一般使用webpack的开头,会有个教程,1.先npminit-y形成package.json,2.然后装webpack和webpack-cli,之后创建一个如下的目录,--save-dev表示开发时......
  • PerfView专题 (第五篇):如何寻找 C# 托管内存泄漏
    一:背景前几篇我们聊的都是非托管内存泄漏,这一篇我们再看下如何用PerfView来排查托管内存泄漏,其实托管内存泄漏比较好排查,尤其是用WinDbg,毕竟C#是带有丰富的元数据......
  • 聊聊客户档案模型的设计与管理
    可以简单,更需要复杂;一、基础描述围绕客户管理通常分为售前、售中、售后、三个核心阶段,即营销、销售、服务三个核心流程与策略,在之前的文章中有聊过CDP系统的设计,本篇从......
  • 持续集成工具篇:Jenkins 与流水线管理【转】
    前言:该文章,围绕持续集成:Jenkins+Docker+K8S相关组件,实现自动化管理源码编译、打包、镜像构建、部署等操作;一、Jenkins安装1、环境部署下载Jenkins包java-jar......
  • 常见docker命令(四)-本地镜像管理
    查看镜像dockerimagesdockerrmi-删除镜像删除mynginx最新镜像dockerrmi-fmynginx:latestdockertag-标记本地镜像,将其归入某个仓库开发一个新地mynginx版本,将其打标......
  • JVM查看内存使用状况
    1、jps:查看本地正在运行的java进程和进程ID(pid)2、jinfopid,查看指定pid的所有JVM信息1)jinfo-flagspid查询虚拟机运行参数信息。2)jinfo-flagnamepid,查询......
  • DNS 管理工具 rndc
    ubuntu20.04的docker环境rndc报错解决http://blog.chinaunix.net/uid-30212356-id-5143959.htmlrndc简介和使用说明https://www.jianshu.com/p/f08cf7cebf3fhttps......
  • fnm node版本管理工具
    推荐一款小巧好用的node管理工具FastNodeManager(fnm)安装(注意添加永久环境变量)#初始安装curl-fsSLhttps://fnm.vercel.app/install|bash#后续升级curl......
  • 视频元信息管理工具
    MetaMovieforMac是一款运行在Mac平台上的电影文件管理工具。MetaMovie也可以添加字幕。要激活字幕下载,您必须首先通过搜索窗口搜索电影。然后在搜索库中按“复制”将信息......