2. 内存管理基础 您所在的位置:网站首页 linux系统需要多大内存够用 2. 内存管理基础

2. 内存管理基础

2023-07-08 15:38| 来源: 网络整理| 查看: 265

内存管理基础

简单来说,编程语言的运行需要调用底层的硬件资源,但是由于资源的稀缺性,这些资源在使用完毕后需要及时的归还和释放,这就是资源管理要做的事情。通常所说的资源,主要包含了硬件中的内存、磁盘/网络IO、文件句柄等。本篇内容主要是针对内存管理进行探讨:

内存分布

在了解内存管理之前,我们需要先明白程序运行过程中,内存是如何分布的。

通常情况下,程序运行过程中,内存区域主要分为以下几部分:

代码区:存放代码编译后的机器码,一般是只读的bss区:存放未初始化的全局变量和静态变量数据区:存放初始化的全局变量和静态变量栈:存放函数参数、局部变量、返回值及其他函数调用信息堆:存放动态分配的内存

其中,1区只读,2&3区在程序运行过程中始终有效,程序结束才会释放,4区仅在线程内共享,5区在进程内共享,4和5区的内存通常由操作系统和编译器负责释放。

内存管理

对于上述内存区域中的1&2&3&4区,因为其生命周期通常可以在编译阶段被确定,所以比较简单。但是对于堆内存的释放,则需要在运行时才能确定,这就是内存管理机制重点要做的事情。目前主流的内存管理方式主要有以下几种:

手动管理:由开发者手动申请和释放资源,如c/c++垃圾回收器GC:由GC负责资源的回收,如java/scala/c#引用计数:编译和运行时对引用计数,小于1时释放,如python所有权机制:通过所有权规则,在编译阶段避免内存问题,如rust

上述几种内存管理方式各有优劣:

手动管理: 比较灵活,但开发效率比较低,而且如果不及时释放内存,则容易造成浪费,所以不太适合可持续的进程如web程序。

垃圾回收器: 将内存回收交给第三方如jvm,需要占用资源进行统计和回收,若降低回收次数,则需要更大内存,通常会降低程序效率。

引用计数: 虽然可以在编译阶段就可以通过预测计数来减少运行负担,但对于某些情况下如递归,则无法进行处理。

所有权机制: 在编译阶段检查静态规则,几乎可以避免全部的内存安全问题,但是学习门槛比较高。

内存泄漏、内存溢出和内存安全

内存管理的主要目标是为了规避内存泄漏、内存溢出和其他内存不安全的问题。

内存泄漏

可以简单理解为内存用过之后不及时释放,一次不释放可以忽略,但长期累积不释放就会造成内存耗尽。在代码中大量使用静态变量、连接资源不及时关闭等都会造成内存泄漏,这在语言层面很难规避,需要养成良好的代码规范来避免这种错误。

内存溢出

与内存泄漏有些像,但又不太一样,都是内存不够用,但是内存溢出是申请内存不够用之后占用了别的内存,形象点讲,内存泄漏是一直在买东西,最后发现钱不够用了,内存溢出则是买了个大件儿,钱不够用,就去抢钱或者贷款了。在代码中一次加载的数据量太大、启动内存太小等都会造成内存溢出,这也需要具体情况进行具体分析。

内存不安全

内存泄漏和内存溢出不属于内存不安全问题,通常情况下内存不安全问题一般是由于对内存的使用不正确造成的,可以归为以下几类:

空指针野指针非法释放缓存区溢出数据竞争

空指针的地址空间一般是受保护的,因此在解引用时会产生segfault。

野指针是指使用了未初始化的内存或者使用已经被释放的内存,总之就是用了不该用的内存。

非法释放是指释放已经释放了的内存或者释放了不该释放的内存。

缓存区溢出通常是指针访问越界,访问了不该访问的地址。

数据竞争是指对同一块内存同时进行写操作并且没有进行同步,这会造成数据不一致。

针对上述这些内存问题,不同语言处理机制不一样,大部分是在运行阶段才发现,但是rust则是通过规则约定,在编译阶段就提前发现问题并规避。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有