C++ malloc/free/new/delete详解(内存管理)

本文详细讲解了malloc/free、brk/mmap在内存分配和释放上的不同,以及new/delete在C++中的内存管理和构造析构函数的应用。着重比较了这些内存管理方式的异同和使用场景,帮助读者理解内存分配的底层原理和最佳实践。
摘要由CSDN通过智能技术生成

malloc/free

典型用法

malloc()负责动态配置内存,大小由size决定,分配成功时返回值为任意类型指针,指向一段可用内存(虚拟内存)的起始地址。分配失败时为NULL。

void * malloc(size_t size)

free()负责释放动态申请的内存空间,调用free( )后ptr所指向的内存空间被收回,如果ptr指向未知地方或者指向的空间已被收回,则会发生不可预知的错误,如果ptr为NULL,free不会有任何作用。

void  free(void *ptr)

内存分配

malloc函数动态申请的内存空间是在堆里(而一般局部变量存于栈里),并且该段内存不会被初始化,如果不采用手动free()加以释放,则该段内存一直存在,直到程序退出才被系统,所以为了合理使用内存,在不适用该段内存时,应该调用free()。另外,如果在一个函数里面使用过malloc,最好要配对使用free,否则容易造成内存泄露。

实现过程

brk和mmap

从操作系统角度来看,malloc的实现有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)。

  1. 申请小于128k的内存时,使用brk分配内存,将数据段.data的最高地址指针_edata向高地址移动,即增加堆的有效区域来申请新的内存空间。
  2. 申请大于128k的内存时,使用mmap分配内存,mmap是在进程的文件映射区找一块空闲存储空间,128K限制可由M_MMAP_THRESHOLD选项进行修改。

这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系

申请小于128k的内存

申请小于128k的内存时,使用brk分配内存,将_edata往高地址推(只分配虚拟空间,不对应物理内存(因此没有初始化),第一次读/写数据时,引起内核缺页中断,内核才分配对应的物理内存,然后虚拟地址空间建立映射关系),如下图:
在这里插入图片描述

  1. 进程启动的时候,其(虚拟)内存空间的初始布局如图1。其中,mmap内存映射文件是在堆和栈的中间(例如libc-2.2.93.so,其它数据文件等),为了简单起见,省略了内存映射文件。_edata指针(glibc里面定义)指向数据段的最高地址。
  2. 进程调用A=malloc(30K)以后,内存空间如图2。malloc函数会调用brk系统调用,将_edata指针往高地址推30K,就完成虚拟内存分配。然而,_edata+30K只是完成虚拟地址的分配,A这块内存现在还是没有物理页与之对应的,等到进程第一次读写A这块内存的时候,发生缺页中断,这个时候,内核才分配A这块内存对应的物理页。也就是说,如果用malloc分配了A这块内容,然后从来不访问它,那么,A对应的物理页是不会被分配的。
  3. 进程调用B=malloc(40K)以后,内存空间如图3。

申请大于128k的内存

申请大于128k的内存时,使用mmap分配内存,在堆和栈之间找一块空闲内存分配,如下图:
在这里插入图片描述

  1. 进程调用C=malloc(200K)以后,内存空间如图4。默认情况下,malloc函数分配内存,如果请求内存大于128K(可由M_MMAP_THRESHOLD选项调节),那就不是去推_edata指针了,而是利用mmap系统调用,从堆和栈的中间分配一块虚拟内存。这样子做主要是因为brk分配的内存需要等到高地址内存释放以后才能
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值