一个c++程序运行的时候,会规划如下内存区域
1、栈stack,存放函数的参数值,局部变量的值等,由系统自动分配,自动释放。先进后出,内存是连续的。
2、堆heap,由程序员分配和释放,若频繁的申请而不释放,就会出现内存泄漏的问题,最后程序结束时可能由os回收。堆内存并不是连续的,更像是数据结构中的链表list。
3、全局静态区,存放全局变量和静态变量,其中初始化的放在一起,非初始化的放在一起。程序结束后由os释放
4、常量区,存放常量,包括字符常量。程序结束后由os释放。
5、程序代码区,存放函数体二进制代码。
栈的简述
栈是一块连续的内存块,不大,超出就出现overflow报错,是从高地址向低地址寻址。由于栈内存是连续分配的,所以读取都比较快。
在函数调用的时候,首先把这个函数的下一个指令地址入栈,这样做是由于栈是先进后出,等调用完函数后得知道下一个调用地址是什么,让程序往下执行下去。
接着把函数的参数从右向左依次压入栈
然后是函数体内的局部变量压入栈,至于静态变量其他的不入栈。
入栈即占用,出栈即释放,而且都是顺序入栈,然后反顺序的出栈,所以就保证了栈的占用是连续性的,所以查找可用的栈内存是很快的。
堆的简述
堆很大,占用是不连续的,当你new一个对象的时候就分配内存,会查询os中的一个链表,这个链表记录可用堆内存的信息。每次查询都会遍历链表,直到找到第一个一块能装下这个对象的内存块,把占用的大小写入第一个地址,剩下的写对象。用不完,占用等这些改变都会在链表中更新信息。所以堆分配内存相对于栈是比较慢的。
如果你用完这个对象,该释放而不释放,那么这个对象对应的内存还是被占用的。这样的对象多了,就会有很多的内存被占用,就造成了内存泄漏。
如果一个指针定义了而没初始化,那么这个指针指向的可能是任意的内存地址,如果这个时候用了这个指针是非常危险的。
如果一个指针内存地址被回收了,但是这个指针没用设置成null,也是很危险的。