C++ 内存分配 学习笔记
1,C++中有5个内存的分配区:堆,栈,常量存储区,自由存储区,全局\静态存储区。
自由存储区,用malloc和free分配和释放,同堆差不多。
全局\静态存储区:用于存储分配的全局和静态变量。
2,堆和栈的区别
主要的区别由以下几点:
1、管理方式不同;堆有编译器管理,栈由程序员管理,比较容易产生memory leak
2、空间大小不同;在32位中,堆理论的大小是4G,所以没有什么限制,但是栈的默认大小是1M,可以设置,但是如果长度过大,会增加内存的开销和启动的时间。
3、能否产生碎片不同;堆用new和delete分配,肯定会造成空间不连续,比较容易产生碎片,栈是按照严格的先进后出的,所以不会产生碎片。
4、生长方向不同;堆是按照地址增加的方向分配的,栈是按照地址减小的方向分配的。
5、分配方式不同;对是动态分配的,没有静态分配的,栈可以是动态分配,也可以是静态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
6、分配效率不同;栈是机器系统提供的数据结构,从底层支持栈的操作,并有专门的指令。所以效率比较高。堆是有C/C++的库来完成的,它的机制很复杂,先需要寻找能分配下的内存地址,然后才能分配。并且还容易造成内存碎片,所以效率比较低。
从这里我们可以看到,堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。
3,重载new和delete修饰符
一个防止堆破碎的通用方法是从不同固定大小的内存持中分配不同类型的对象。对每个类重载new 和delete就提供了这样的控制。
可以很容易地重载new 和 delete 操作符,如下所示:
void * operator new(size_t size) { void *p = malloc(size); return (p); } void operator delete(void *p); { free(p); } |
也可以对单个类的new 和 delete 操作符重载。这是你能灵活的控制对象的内存分配。
class TestClass { public: void * operator new(size_t size); void operator delete(void *p); // .. other members here ... }; void *TestClass::operator new(size_t size) { void *p = malloc(size); // Replace this with alternative allocator return (p); } void TestClass::operator delete(void *p) { free(p); // Replace this with alternative de-allocator } |
所有TestClass 对象的内存分配都采用这段代码。更进一步,任何从TestClass 继承的类也都采用这一方式,除非它自己也重载了new 和 delete 操作符。通过重载new 和 delete 操作符的方法,你可以自由地采用不同的分配策略,从不同的内存池中分配不同的类对象。
必须小心对象数组的分配。你可能希望调用到被你重载过的new 和 delete 操作符,但并不如此。内存的请求被定向到全局的new[ ]和delete[ ] 操作符,而这些内存来自于系统堆。
C++将对象数组的内存分配作为一个单独的操作,而不同于单个对象的内存分配。为了改变这种方式,你同样需要重载new[ ] 和 delete[ ]操作符。
class TestClass { public: void * operator new[ ](size_t size); void operator delete[ ](void *p); // .. other members here .. }; void *TestClass::operator new[ ](size_t size) { void *p = malloc(size); return (p); } void TestClass::operator delete[ ](void *p) { free(p); } int main(void) { TestClass *p = new TestClass[10]; // ... etc ... delete[ ] p; } |
但是注意:对于多数C++的实现,new[]操作符中的个数参数是数组的大小加上额外的存储对象数目的一些字节。在你的内存分配机制重要考虑的这一点。你应该尽量避免分配对象数组,从而使你的内存分配策略简单。
4,常见的内存错误
【1】:内存没有分配成功,但是却使用了这个分配的内存。(办法是判断一下是否为NULL assert(P == NULL)).
【2】:分配了内存却没有初始化,及时初始化为0.
【3】:数组越界,特别要当心发生“多1”或者“少1”操作。
【4】:释放了内存没有置为空,用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。
【5】:释放了的内存还去引用
【6】:new和delelte要成对出现(malloc和free也是一样)
转载于:https://www.cnblogs.com/endeavour/archive/2011/11/17/2252584.html
C++ 内存分配 学习笔记相关推荐
- Windows内存管理学习笔记(三)—— 无处不在的缺页异常
Windows内存管理学习笔记(三)-- 无处不在的缺页异常 缺页异常 实验一:设置虚拟内存 无处不在的缺页 位于页面文件 保留与提交的误区 实验二:理解缺页异常 EXECUTE_WRITECOPY ...
- Windows内存管理学习笔记(一)—— 线性地址的管理
Windows内存管理学习笔记(一)-- 线性地址的管理 用户空间线性地址的管理 实验一:理解用户空间线性地址管理 Private Memory 实验二:理解Private Memory 堆 实验三: ...
- 郝健: Linux内存管理学习笔记-第5节课
前序文章: 郝健: Linux内存管理学习笔记-第1节课 郝健: Linux内存管理学习笔记-第2节课 郝健: Linux内存管理学习笔记-第3节课 郝健: Linux内存管理学习笔记-第4节课 摘要 ...
- 郝健: Linux内存管理学习笔记-第4节课
前序文章: 郝健: Linux内存管理学习笔记-第1节课 郝健: Linux内存管理学习笔记-第2节课 郝健: Linux内存管理学习笔记-第3节课 摘要 page cache free命令的详细解释 ...
- Windows内存管理学习笔记(二)—— 物理内存的管理
Windows内存管理学习笔记(二)-- 物理内存的管理 物理内存 实验一:理解MmNumberOfPhysicalPages MmPfnDatabase _MMPFN 物理页状态 六个链表 实验二: ...
- 郝健: Linux内存管理学习笔记-第6节课
前序文章: 郝健: Linux内存管理学习笔记-第1节课 郝健: Linux内存管理学习笔记-第2节课 郝健: Linux内存管理学习笔记-第3节课 郝健: Linux内存管理学习笔记-第4节课 郝健 ...
- dma_alloc_coherent DMA内存申请学习笔记
说明 dma_alloc_coherent 相关的知识网络上有很多,将相关的知识收集汇总以便于后续遇到问题方便查找.这一次对dma_alloc_coherent进行学习的原因是在使用rapidio驱动 ...
- Java虚拟机内存区域---学习笔记
Java虚拟机 虚拟机: 定义:模拟某种计算机体系结构,执行特定指令集的软件. 种类: 系统虚拟机(Virtual Box .VMware) 进程虚拟机(JVM.Adobe Flash Player. ...
- Java虚拟机专题之内存分配(读书笔记)
一 虚拟机内存分配策略 1.1 对象优先在Eden区域分配 1.2 大对象直接进入老年代 1.3 长期存活的对象进入老年代 1.4 空间分配担保 1.5 动态对象年龄判定 二 对象优先在Eden区域分 ...
最新文章
- /* * 编程第一题(20分): 	1+(1+2)+(1+2+3)+……+(1+2+3+……+98+99+100) */
- axure小程序模板_微信小程序模板案例收集
- 杭电oj2043密码
- 将一个项目中已有的文档添加到另一个项目中的方法
- hadoop+hive-0.10.0完全分布式安装方法
- 放弃第三方?苹果正自研iPhone调制解调器芯片
- Android调用系统相册、拍照以及裁剪最简单的实现(兼容7.0)
- 前n个正整数相乘的时间复杂度为_初一数学必考的21个知识点,附考试重难点,预习必备!...
- C# 基础(十八)C# 工程自动生成app.manifest、AssemblyInfo.cs、Resources.Designer.cs、Settings.Designer.cs文件的作用
- 轻松办公信息化,六大OA产品优劣点评
- PHP+经贸时间轴 毕业设计-附源码211617
- 植物大战僵尸最全最新版修改存档
- 题解-[Usaco2005 Mar]Out of Hay 干草危机
- 警告:Named Route ‘Main‘ has a default child route. When navigating to this named route
- 计算机一级重点复习提纲,计算机一级B考试复习提纲是什么?
- 办公室桌面计算机,我的办公室桌面(一切为了简洁)
- Win7激活后添加grub引导Linux最简单方法
- 【期末考试】计算机组成原理突击复习
- 应用于双麦克风小型手持设备的语音降噪方法
- 【Java】什么是二方库?
热门文章
- Navicat 连接MySQL 8.0.11 出现2059错误
- SpringBoot接收数组参数
- echarts自定义y轴刻度信息
- Docker镜像源更改
- SiteMesh JSP布局框架介绍
- 【CCCC】PAT : 团体程序设计天梯赛-练习集 L3 答案(01-23)
- 【NOIP2015】【Luogu2615】神奇的幻方(模拟填数)
- 动态调试 ida linux,IDA动态调试-ELF
- 虚拟机服务器配置毕业论文,基于Vmware的服务器虚拟化管理-毕业论文.doc
- 哪个相机可以拍gif动图_你见过最搞笑的gif是什么?那些搞笑的动图都是用什么gif制作app制作的?...