动态内存管理:malloc/free/new/delete/brk/mmap
这是我去腾讯面试的时候遇到的一个问题——malloc()是如何申请内存的?
c++ 内存获取和释放 new/delete,new[]/delete[]
c 内存获取和释放 malloc/free, calloc/realloc
上述8个函数/操作符是c/c++语言里常用来做动态内存的申请和释放的,要理解这些接口,大概需要
下面几个维度的了解:
1. 了解OS的进程空间模型,一个进程的地址空间,一般划分为内核区、用户区,用户区又划分为栈区、堆区、数据区、代码区。
这里的‘堆区’,‘栈区’,‘数据区’,‘内核区’,其实就是一个虚拟地址区间,动态内存最终都是从OS的'堆区'上获取的。
2. brk、mmap 系统调用
brk系统调用,可以让进程的堆指针增长一定的大小,逻辑上消耗掉一块本进程的虚拟地址区间,malloc向OS获取的内存大小比较小时,将直接通过brk调用获取虚拟地址,结果是将本进程的brk指针推高。
mmap系统调用,可以让进程的虚拟地址区间里切分出一块指定大小的虚拟地址区间vma_struct,并返回给用户态进程,被mmap映射返回的虚拟地址,逻辑上被消耗了,直到用户进程调用munmap,才回收回来。malloc向系统获取比较大的内存时,会通过mmap直接映射一块虚拟地址区间。mmap系统调用用处非常多,比如一个进程的所有动态库文件.so的加载,都需要通过mmap系统调用映射指定大小的虚拟地址区间,然后将.so代码动态映射到这些区域,以供进程其他部分代码访问;另外,多进程通讯,也可以使用mmap,这块另开文章详解。
无论是brk还是mmap返回的都是虚拟地址,在第一次访问这块地址的时候,会触发缺页异常,然后内核为这块虚拟地址申请并映射物理页框,建立页表映射关系,后续对该区间虚拟地址的访问,通过页表获取物理地址,然后就可以在物理内存上读写了。
3. malloc/free 是libc库函数
malloc/free是 libc实现的库函数,主要实现了一套内存管理机制,当其管理的内存不够时,通过brk/mmap等系统调用向内核申请进程的虚拟地址区间,如果其维护的内存能满足malloc调用,则直接返回,free时会将地址块返回空闲链表。
malloc(size) 的时候,这个函数会多分配一块空间,用于保存size变量,free的时候,直接通过指针前移一定大小,就可以获取malloc时保存的size变量,从而free只需要一个指针作为参数就可以了calloc 库函数相当于 malloc + memset(0)
除了libc自带的动态内存管理库malloc, 有时候还可以使用其他的内存管理库替换,比如使用google实现的tcmalloc ,只需要编译进程时链接上 tcmalloc的静态库并包含响应头文件,就可以透明地使用tcmalloc 了,与libc 的malloc相比, tcmalloc 在内存管理上有很多改进,效率和安全性更好。
4. new/new[]/delete/delete[]
new/delete 是c++ 内置的运算符,相当于增强版的malloc/free. c++是兼容c的,一般来说,同样功能的库,c++会在安全性和功能性方面
比c库做更多工作。动态内存管理这块也一样。
new的实现会调用malloc,对于基本类型变量,它只是增加了一个cookie结构, 比如需要new的对象大小是 object_size, 则事实上调用 malloc 的参数是 object_size + cookie, 这个cookie 结构存放的信息包括对象大小,对象前后会包含两个用于检测内存溢出的变量,所有new申请的cookie块会链接成双向链表。由于内置了内存溢出检测,所以比malloc更安全。
对于自定义类型,new会先申请上述的大小空间,然后调用自定义类型的构造函数,对object所在空间进行构造。c++比c强大的一个方面
就是c++编译器可以自动做构造和析构,new运算符会自动计算需要的空间大小,然后根据类型自己调用构造函数,如果存在子类型对象,或者存在继承的基类型,new都会自动调用子类型的构造函数和基类型的构造函数完成构造。同样,delete 操作符根据cookie的size知道object的大小,如果是自定义类型,会调用析构函数对object所在空间进行析构,如果有子类型或继承,自动调用子类型和基类型的析构函数,然后将cookie块从双向链表摘除,最后调用 free_dbg 释放。
new[] 和delete[]是另外两个操作符,用于数组类型的动态内存获取和释放,实现过程类似new/delete
动态内存管理:malloc/free/new/delete/brk/mmap的更多相关文章
- 动态内存管理详解:malloc/free/new/delete/brk/mmap
c++ 内存获取和释放 new/delete,new[]/delete[] c 内存获取和释放 malloc/free, calloc/realloc 上述8个函数/操作符是c/c++语言里常用来做动 ...
- 操作系统动态内存管理——malloc和free的工作机制
动态内存分配 就 是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法. malloc()是C语言中动态存储管理 的一组标准库函数之一.其作用是在内存的动态存储区中分配一个长度为size的 ...
- 动态内存管理---new&delete
动态内存管理 动态对象(堆对象)是程序在执行过程中在动态内存中用new运算符创建的对象. 因为是用户自己用new运算符创建的.因此也要求用户自己用delete运算符释放,即用户必须自己管理动态内存. ...
- C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)
C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...
- C++中对C的扩展学习新增语法——动态内存管理
1.C语言动态内存管理的缺点: 1.malloc对象的大小需要自己计算. 2.需要手动转换指针类型. 3.C++的对象不适合使用malloc和free. 2.C++中new/delete基本使用: 3 ...
- C++动态内存管理与源码剖析
引言 在本篇文章中,我们主要剖析c++中的动态内存管理,包括malloc.new expression.operator new.array new和allocator内存分配方法以及对应的内存释放方 ...
- C++动态内存管理之shared_ptr、unique_ptr
C++中的动态内存管理是通过new和delete两个操作符来完成的.new操作符,为对象分配内存并调用对象所属类的构造函数,返回一个指向该对象的指针.delete调用时,销毁对象,并释放对象所在的内存 ...
- uCGUI动态内存管理
动态内存的堆区 /* 堆区共用体定义 */ typedef union { /* 可以以4字节来访问堆区,也可以以1个字节来访问 */ ]; /* required for proper aligne ...
- Keil C动态内存管理机制分析及改进(转)
源:Keil C动态内存管理机制分析及改进 Keil C是常用的嵌入式系统编程工具,它通过init_mempool.mallloe.free等函数,提供了动态存储管理等功能.本文通过对init_mem ...
随机推荐
- mysql,字符串类型id,获取最大值
说明,这个id是字符串类型,但是实际值是一个整数,获取最大值的方法是: select max(cast(id as SIGNED)) from table 另外,mysql生成伪列的方法: SELEC ...
- 《Interest Rate Risk Modeling》阅读笔记——第四章:M-absolute 和 M-square 风险度量
目录 第四章:M-absolute 和 M-square 风险度量 思维导图 两个重要不等式的推导 关于 \(M^A\) 的不等式 关于 \(M^2\) 的不等式 凸性效应(CE)和风险效应(RE)的 ...
- SpringCloud与Dubbo区别对比
1:SpringCloud与Dubbo区别对比 (1):活跃度 目前SpringCloud的活跃度明显远高于Dubbo(参考github) (2):主要区别 Dubbo Spring Cloud ...
- springboot 获取到的inputStream为空的问题
springboot在接收http请求的时候读取的request的inputStream,造成我们想自己读取inputStream的时候发现inputStream已经无法读取了. 为了读取inputS ...
- 如何在 ubuntu 下使用 Windows 里面的字体
01. 02. 03. 04. 谢谢浏览!
- 一个JS正则的字符串替换函数
直接上函数吧 不废话 function replacestring(oldstr,newstr,text) { var exp = new RegExp(oldstr,'g'); var c=tex ...
- 优化、分析Mysql表读写、索引等操作的sql语句效率优化问题
为什么要优化: 随着实际项目的启动,数据库经过一段时间的运行,最初的数据库设置,会与实际数据库运行性能会有一些差异,这时我们 就需要做一个优化调整. 数据库优化这个课题较大,可分为四大类: >主 ...
- Linq与委托
using System; using System.Linq; using System.Reflection; using Stuglxt_Models; namespace ConsoleApp ...
- webapi ClaimsPrincipal使用
参考文档:ClaimsPrincipal Class 个人demo:SwaggerDemoApi 今天看到一段代码懵逼了 var principal = new ClaimsPrincipal(new ...
- PIE SDK加载WMS服务数据
1. 功能简介 WMS服务,WMS是OGC标准中比较简单也是比较重要的标准之一.它全称是“Web Map Service”(网络地图服务):利用具有地理空间位置信息的数据制作地图.其中将地图定义为 ...