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

5. 参考

http://blog.csdn.net/ubuntulover/article/details/7581317

http://blog.csdn.net/szlanny/article/details/4249768

动态内存管理详解:malloc/free/new/delete/brk/mmap的更多相关文章

  1. 动态内存管理:malloc/free/new/delete/brk/mmap

    这是我去腾讯面试的时候遇到的一个问题——malloc()是如何申请内存的? c++ 内存获取和释放 new/delete,new[]/delete[] c 内存获取和释放 malloc/free, c ...

  2. 转:C/C++内存管理详解 堆 栈

    http://chenqx.github.io/2014/09/25/Cpp-Memory-Management/ 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了 ...

  3. C/C++内存管理详解

    内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存泄 ...

  4. C/C++内存管理详解 ZZ

    内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的 检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存 ...

  5. C/C++内存管理详解(转)

    内存分配方式 简介 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动 ...

  6. 【转载】C/C++内存管理详解

    转自:http://chenqx.github.io/2014/09/25/Cpp-Memory-Management/ 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中 ...

  7. Apache Spark 内存管理详解(转载)

    Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优.本文旨在梳理出 ...

  8. spark内存管理详解

    Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优.本文旨在梳理出 ...

  9. java之 JVM 内存管理详解

    一.JVM结构 根据<java虚拟机规范>规定,JVM的基本结构一般如下图所示: 从左图可知,JVM主要包括四个部分: 1.类加载器(ClassLoader):在JVM启动时或者在类运行时 ...

随机推荐

  1. linpack_2

    Run linpack in server 1.Get computer nodal information lscpu dmidecode -t memory | head -45 | tail - ...

  2. 11,flask之--WTForms

    WTForms是什么? 相当于django的ModelForm. 在网页中,为了和用户进行信息交互总是不得不出现一些表单.flask设计了WTForm表单库来使flask可以更加简便地管理操作表单数据 ...

  3. springboot遇见问题总结

    今天开始学习创建springboot项目 问题1: 产生异常: 创建项目目录: demo代码: 代码Controller import org.springframework.web.bind.ann ...

  4. 强烈推荐android初学者,android进阶者看看这个系列教程

    强烈推荐android初学者,android进阶者看看这个系列教程 转载 2015年05月30日 23:05:44 695 为什么要研究Android,是因为它够庞大,它够复杂,他激起了我作为一个程序 ...

  5. 剑指Offer - 九度1509 - 树中两个结点的最低公共祖先

    剑指Offer - 九度1509 - 树中两个结点的最低公共祖先2014-02-07 01:04 题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样 ...

  6. 《Cracking the Coding Interview》——第2章:链表——题目3

    2014-03-18 02:25 题目:给定一个单链表中间的节点,删掉那个节点. 解法:把后面节点的数据域拷到当前节点来,然后删除后面那个节点.当前节点不是尾巴,所以后面不为空. 代码: // 2.2 ...

  7. Django笔记 —— 模型

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  8. dynamic基元类型与隐式类型的局部变量var

    dynamic代码示例 using System; using System.Collections.Generic; using System.Linq; using System.Text; na ...

  9. Python全栈 MySQL 数据库(SQL命令大全、MySQL 、Python调用)

    为了梦想与了信仰    开局一张图   主要三个方面: 1.Linux终端命令 2.MySQL语句 3.Python调用   先删库 再跑路.....                         ...

  10. 如何将查询到的数据显示在DataGridView中

    背景介绍: 数据库中的T_Line_Info表中存放着学生上机的记录,也就是我们需要查询上机记录的表,其中具体内容为: 界面设计如下: 右击DataGridView控件,选择编辑列,设计它的列名. 代 ...