写在前面
局部变量区即栈区;动态存储区,即堆(heap)区或自由存储区(free store);
c++中程序占用的内存分为一下的几个部分
- 栈区:一般存放的是值类型,由编译器自动分配、释放;存放的是函数的参数值,局部变量的值等,其操作方式类似数据结构的栈;
- 堆:存在于堆中的数据一般是通过程序员进行主动释放,如果程序员没有主动释放,那么在程序结束的时候,由操作系统进行回收,如那些由new分配的内存块,他们的释放,编译器并不管,而是通过程序员释放(delete),如果程序员没有释放掉,那么程序结束之后,操作系统会自动回收;
- 静态区:静态区存放的是静态变量(全局变量和静态变量是存放在一起的);
- 常量区:常量存储的地方,由操作系统释放;
- 程序代码区:存放函数体的二进制代码;
详细讲解堆栈:
void f() { int* p=new int[5]; }
在这句话中,首先看到new 知道这句话会在堆区开辟一块内存,然后再看到p是一个局部变量,那么会在栈区开辟一段内存来保存p,所以这句话的意思就是,在栈中有一个指针p,p指向的是堆中的一段内存
堆和栈的主要区别:
- 管理方式不同:对于栈来说,他的内存是通过编译器自动释放的,而对于堆来说,是需要程序员进行释放的,否则容易产生内存泄漏
- 能否产生碎片:对于堆来说,由于是通过new/delete 来进行开辟与删除的,但是这样做的坏处就是,造成内存的不连续,从而会造成大量的内存碎片
- 分配效率:对于堆来说,由于会涉及到new/delete,所以会造成大量的内存碎片,可能会引发用户态和和心态的转变,内存的申请等,所以效率很低,而在程序中,一般推荐是用栈而不是使用堆;
- 分配方式:对于堆来说,堆全部都是动态分配的,而对于栈来说,有两种方式,一种是静态分配,一种是动态分配,静态的分配是编译器完成的,而动态分配是通过malloc进行分配的,这个动态分配和堆的动态分配不同,栈的动态分配是不需要我们参与释放的,而是通过编译器的自动释放;
堆栈上的内存操作越界问题:
- 堆的内存越界主要是因为操作的内存超过了calloc/malloc/new等在对上分配内存函数所分配的大小,后果就是在下次calloc/malloc/new的失败
- 栈内存越界的情况大多数出现在对数组的操作上,比如,对数组下标的操作,下标超出了数组定义的长度;