【高质量C++/C总结6】内存管理——堆(stack)栈(heap)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ModestBean/article/details/85258980

说在开始:

我提炼了《C++ Primer》、《侯捷C++》、《高质量程序设计指南——C/C++语言》等资料中的重要部分,并总结成此博文。其中涉及到许多我个人对C++的理解,如若有不合理之处,还请朋友们多多指出,我会虚心接受每一个建议。同时,我将实现代码放到了我的GitHub上https://github.com/ModestBean/C-Samples,可供下载参考。

内存分配方式——堆栈(stack)和栈(heap)

堆栈(stack)

存在于某一个作用域的存储空间。在函数执行期间,函数内部分局部变量和形参都会创建在堆栈上。在函数执行结束时,存储单元会自动在堆栈中清退。由系统分配,分配速度比较快,效率比较高。一般情况不会出现错误,但是有时会出现退栈溢出。

堆(heap)

由系统提供的一块全局的内存空间,程序在运行过程中需要使用malloc或者new申请任意数量的内存,可称为动态内存分配,使用非常灵活但是也非常出现问题。

两者申请方式

void function(){
    Object a;//在堆栈(stack)
    Object *b=new Object();//在堆(Heap)
}

在这段代码中应该注意,a是存在堆中的,在函数消亡后就不可在使用,尤其注意不可以使用对象a的引用,因为引用一个不存在的对象是不太现实的。 而对象b在程序的运行过程中都会存在,直到手动delete或者free后才不可以在使用。

两者申请过程

stack:只要栈还有足够的剩余空间,系统都会给程序进行分配,否则分配失败

heap:应用程序调用操作系统OS的内存管理模块,搜索其中是否含有符合要求的空闲连续字节内存块。在操作系统中,多次进行动态内存分配后,会产生许多内存碎片,操作系统可能首先需要整理内存碎片,然后才能分配成功,在这种情况下就需要很长的时间。

如果对上面的话理解起来有困难,可以参考一下书籍《操作系统》中内存管理的章节。

空间大小比较

stack:是一块内存连续区域,也就是说,栈的首地址和大小都是一开始定义好的。如果申请空间大于栈的空间就会出现溢出的现象。默认的堆空间都不大,大概是1M,2M。

heap:在操作系统中,是不连续的内存区域,是由操作系统的空闲内存链表来控制的,(关于空闲内存链表的问题,可以查看操作系统的书籍),堆的大小由虚拟内存影响,堆的申请空间比较大,但是有时申请速度可能比堆慢。

堆栈中的存取内容

stack:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

heap:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

其他堆栈内容

(1)还有另外一种内存分配方式:从静态存储区分配,这段内存在程序编译的时候就是确定的,在程序的整个运行期间都是存在的,例如全局变量和static变量等等。

(2)在动态内存中,开发人员需要检查返回值和捕获异常,来确保内存分配是否成功,这需要额外的开销。千万不要认为这种这种开销是可以避免的。千万不要因小失大。

(3)动态内存创建的对象需要手动delete,甚至在删除后还会继续使用,或者根本就不回删除,这时程序就会出现内存泄漏等现象。同时这些错误也是不容易被发现的。

猜你喜欢

转载自blog.csdn.net/ModestBean/article/details/85258980