当前位置:首页 > 内存 > 正文

内存分配函数(调用函数时将为形参分配内存单元)

  • 内存
  • 2024-06-13 09:44:34
  • 2391

一、内存分配(malloc)的过程

[TOC]

内存分配函数如malloc和mmap仅设置进程的虚拟地址空间,并不分配实际的物理内存。当进程访问不存在映射关系的虚拟内存时,会自动触发缺页中断。

在需要分页的系统中,可以查询页表的当前状态位来检查当前页是否在内存中。如果内存中没有,您可以读取缺失的页面。内存页表中的外部内存地址。例如,映射文件mmap.

使用命令ps-omajflt、minflt-Cprogram查看。

majflt是Majorfault(需要读盘)的缩写,中文名称是majorfailure,minflt是Minorfault(不需要读盘)的缩写,中文名称是minorfault。

这两个值代表自一个进程启动以来发生的页面错误的数量。

当进程中发生页面错误时,该进程进入内核模式并执行以下操作:

如果在步骤3中需要读取磁盘,则此页面有一个中断错误是一件严重的事情,否则就是一件小事。

从操作系统的角度来看,进程分配内存有两种方式,通过两个系统调用来完成:brk和mmap(不考虑共享内存)。

这两种方法都分配虚拟内存,不分配物理内存。当分配的虚拟地址空间第一次被访问(读/写)时,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。

标准C库中提供了malloc/free函数来分配和释放内存。这两个函数底层是通过brk、mmap、munmap等系统调用来实现的。

如果malloc内存小于128k,则使用brk分配内存,并将_edata推送到更高的地址

对于malloc内存大于128k,使用mmap分配内存,并在之间查找堆和栈部分分配空闲内存(对应独立内存,初始化为0)

上一节介绍了mmap的内存释放。这里我们主要关注释放mmap的内存。brk

既然brk堆中的内存不能直接释放,那为什么不使用mmap分配,然后munmap直接释放呢?
其实,事务sbrk/mmap/munmap接口就是使用的操作系统注册和释放地址空间的过程都是系统调用,系统调用经常消耗系统资源。而且,一旦mmap申请的内存是munmap,重新申请会产生更多的分页符。例如使用mmap分配1M空间,第一次调用会产生大量缺页中断(1M/4K次)。当使用munmap重新分配1M空间时,会产生量缺页中断。再次。页面错误中断是一种内核行为,会导致内核模式下CPU消耗较高。另外,如果使用mmap分配小内存,会导致更多的地址空间碎片,给内核带来更大的管理负担。
此外,堆是一个连续的空间,堆中的段不会返回给操作系统。如果这些段可以重用,那么重新访问内存可能不需要任何系统调用和分页符。,这将显着降低CPU消耗。因此,glibc对m​​alloc的实现充分考虑了brk和mmap操作上的差异和优缺点。默认情况下,在使用mmap获取地址空间之前会分配一大块内存(128k)。mallopt(M_MMAP_THRESHOLD,)这个键值。


二、编译过程中内存的分配与释放

在编译过程中,内存的分配和释放是一个非常重要的环节。栈空间和堆空间是内存管理中的两个重要概念,各自具有独特的特点和用途。本文将深入探讨栈空间和堆空间的区别,以及它们在内存管理中的作用。
📚栈空间和堆空间的区别
栈空间是由操作系统(编译器)自动管理的。它为变量和函数提供临时存储空间,并在运行时进行参数传递。。堆空间是在程序运行时动态分配的,大小可以根据需要调整。相比之下,堆内存分配由C/C++函数库来处理,具有更大的灵活性和方便性。
🚀堆内存分配的效率问题
堆内存分配由C/c++函数库处理,具有更大的灵活性和方便性。但由于涉及动态分配,其效率可能会受到影响。程序员在使用堆内存时需要注意尽可能减少内存分配次数,以提高程序效率。
🔗栈空间和堆空间的联系
在内存管理方面,堆通常用来保存新创建的对象和数组,由虚拟机的自动垃圾收集器管理机器。当在堆中创建数组或对象时,可以在堆栈上设置一个引用变量,使其值等于堆中数组或对象的地址。这样我们就可以通过这个引用来访问堆中的数据了。
💡堆内存管理
程序员通常负责管理堆内存的分配。需要注意的是,如果数组或对象没有指向它的引用变量,即使在堆中分配内存,也会造成内存浪费,因为垃圾收集器无法在不确定的时间释放这部分内存。


三、C语言malloc()函数分配内存空间尺寸的问题

这个问题首先得从栈说起,一个程序一般分为三部分:代码部分;数据部分(静态数据)和堆栈部分。堆栈部分存储程序中的变量;存储程序传递的参数等(动态分配的变量存储在堆上,静态分配的变量存储在堆栈上)。堆栈按以下方式增长:

程序将在运行时预先分配堆栈空间,因此您的查询不会修改不应该修改的部分。改造原本是徒劳的。


返回malloc函数;malloc主要负责分配空间并返回空间的首地址。那么为什么请求的空间是0却可以存储7个字符呢?这是因为C语言中的指针不检查数组越界问题。您可以使用以下命令执行此操作:chach[5];然后读写ch[6](printf或scanf)。并且不会报错。但当我们使用它的时候,因为这种程序是非常危险的,如果它使用的地址是操作系统地址。如果您在更新后使用它。,系统将会崩溃。同时,由于C语言机制被黑客广泛用于缓冲区溢出攻击,因此参数内部不能使用指。你总是要考虑是否会越界来提升指针(数组)。程序的安全性。


希望这对您有帮助。。。