在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(通过非正当手段也可以修改)
void f() { int* p=new int[5]; }
在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中
00401028 push 14h
0040102A call operator new (00401060)
0040102F add esp,4
00401032 mov dword ptr [ebp-8],eax
00401035 mov eax,dword ptr [ebp-8]
00401038 mov dword ptr [ebp-4],eax
释放内存是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie信息去进行释放内存的工作。
堆和栈的区别
1、管理方式不同;
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
2、空间大小不同;
空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M。当然,我们可以修改: 打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。
3、能否产生碎片不同;
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出。
4、生长方向不同;
生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
5、分配方式不同;
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
6、分配效率不同;
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
从这里我们可以看到,堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以尽量用栈,而不是用堆。
虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。
无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果。
相关推荐
讲述C++开发中变量及方法对内存的占用及释放情况
带这个问题与本中心庄鹏飞老师讨论之后,发现原来我没有搞清楚在C++中指针分为栈指针和堆指针。参见int* Test::getArray()方法中关于数组的声明以及本人非常详细的说明,那么我想会给学习C++编程的人员带来收获。 ...
1 简述C、C++程序编译的内存分配情况 2 谈谈你对拷贝构造函数和赋值运算符的认识 3 用C++设计一个不能被继承的类 4 简述队列和栈的异同 5 深拷贝和浅拷贝的区别是什么 6 栈上分配内存和堆上分配内存有什么区别? 7 ...
内存分配中,堆分配和栈分配有什么差别? 这两种方式是不相同的。声明变量/数组的方式,是在栈中分配内存。程序中的每一个函数都有自己的栈,用于为函数作用域内的变量/对象分配存储空间。当调用完此函数返回的时候...
内存分配方式及其区别,包括静态存储区、栈和堆。 const关键字与#define宏定义的比较和应用。 数组与指针的区别和内存容量计算。 函数指针的声明和使用。 程序跳转到指定内存地址的方法。 全局变量与局部变量的区别...
golang 的内存分配之堆和栈 Go的垃圾回收,让堆和栈堆程序员保持透明。真正解放了程序员的双手,让他们可以专注于业务,“高效”地完成代码编写。把那些内存管理的复杂机制交给编译器。 栈 可以简单得理解成一次函数...
12.1.1C从堆中获取存储单元的方法 12.1.2运算符new 12.1.3运算符delete 12.1.4一个简单的例子 12.1.5内存管理的开销 12.2重新设计前面的例子 12.2.1仅从堆中创建string类 12.2.2stash指针 12.2.3stack例子 12.3用于...
在大部分系统语言中,比如 C 和 C++,您必须进行内存管理。本文将介绍手工的、半手工的以及自动的内存管理实践的基本概念。 追溯到在 Apple II 上进行汇编语言编程的时代,那时内存管理还不是个大问题。您实际上在...
C++片段2 指针、多态和内存分配 113 C2.1 变量的内存分配和方法的前期绑定 114 C2.2 需要解决的问题 115 C2.3 指针与程序的自由存储 116 C2.3.1 释放内存 118 C2.3.2 避免内存泄漏 119 C2.3.3 避免悬挂指针 ...
*7.1.7 动态分配和撤销内存的运算符new和delete 7.2 共用体 7.2.1 共用体的概念 7.2.2 对共用体变量的访问方式 7.2.3 共用体类型数据的特点 7.3 校举类型 7.4 用typedef声明类型 习题 第3篇 基于对象的程序设计 第...
《visual c++ 2010入门经典(第5版)》针对visual c++ 2010版本进行了全面更新,介绍了最新的开发环境和如何使用visual c++构建现实世界中的应用程序。拥有本书,您就迈向了通往使用两种c++版本编写应用程序的成功之路...
面试题18:简述C、C++程序编译的内存分配情况 面试题19:以下四段代码中哪段没有错误 第6章 字符串 6.1 数字字符串 面试题1:编码实现数字转化为字符串 面试题2:编码实现字符串转化为数字 6.2 字符串函数 面试题3:...
13.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中? 答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理 堆: 程序运行时动态申请,new 和 malloc申请的内存就在堆上 14....
2012-06-11 08:57 88,576 C++ 开发中内存分配及堆和栈的区别.doc 2012-06-11 08:52 190,100 C++中二维数组与指针关系的剖析.pdf 2012-06-11 08:48 171,862 C++函数后加const的意义.pdf 2012-06-11 08:57 9,174 C++...
master分支:master分支分析:文档(通过执行./make_test.sh 8生成):HTML libsrt已包含在Paul Hsieh的“字符串库比较”...它的设计旨在避免在使用动态大小的数据结构时避免显式的内存管理,从而实现安全且具有表现力
*7.1.7 动态分配和撤销内存的运算符new和delete 7.2 共用体 7.2.1 共用体的概念 7.2.2 对共用体变量的访问方式 7.2.3 共用体类型数据的特点 7.3 校举类型 7.4 用typedef声明类型 习题 第3篇 基于对象的程序设计 第...
7.2 不同类型的内存分配 7.2.1 虚拟内存 7.2.2 堆 7.2.3 本地堆 7.2.4 独立堆 7.2.5 栈 7.2.6 静态数据 7.2.7 字符串资源 7.2.8 选择适当的内存类型 7.2.9 管理低内存状态 第8章 模块、进程和线程 8.1 模块 8.2 ...
在我们用C/C++开发的过程中,总是有一个问题会给我们带来苦恼。这个问题是函数内和函数外代码需要通过一块内存来交互(比如,函数返回字符串),这个问题困扰和很多开发人员。如果你的内存是在函数内栈上分配的,...
程序员面试刷题的书哪个...内存中的栈和堆分配 2 面对对象基础 (务必熟悉底层机制原理) 面向对象理解 析构函数 构造函数 拷贝构造 多态 纯虚函数和虚函数 虚函数实现机制 虚函数表 访问限定符 public、private、prote