栈空间和堆空间的内存增长方向不一样。栈空间是从高地址向低地址增长的过程,堆空间是从低地址向高地址增长的过程。内存正常都是从低地址向高地址增长。
栈空间中的变量定义好后,这个变量的内部存储、资源分配的操作完全交由编译器和系统来完成。堆区的变量由程序员动态的创建。当然我们new出空间后要记得delete,不然会造成内存泄漏。
在堆区和常量区之间还有一个常量区,图中没有体现出来。
常量区分为全局初始化区和全局未初始化区。
堆是一种动态分配资源的方式,从现代编程语言角度看,动态分配内存是一件很自然的事情。动态分配内存可以由程序员来掌握,但是会带来一些不确定性:内存分配耗时需要多久?失败了怎么办?在实时性要求比较高的场合,比如一些嵌入式控制器和电信设备,这些情况就不容忽视,所以这些场合一般使用C++而不是java(java一般全是在堆中分配)。
一般而言,但我们在堆上分配内存时,很多语言会使用new这样的关键字,有些语言则是隐式分配。在C++中new对应的是delete,这样可以让程序员完全接管内存的分配和释放。
程序通常需要牵涉到三个内存管理器的操作,C++做了1、2两件事,java做了1、3两件事:
分配一个某大小的内存块;释放一个之前分配的内存块;垃圾收集操作,寻找不再使用的内存块并予以释放。这个回收策略需要实现性能、实时性、额外开销等放面的平衡,很难有统一和高效的做法。内存泄漏是指程序中已经动态分配的堆内存由于某种原因程序没有释放或者无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统程序崩溃等严重后果。
内存泄漏发生原因和排查:
内存泄漏主要发生在堆内存分配方式中,即“配置了内存后,所有指向该内存的指针都遗失了”。若缺乏垃圾回收机制,这样的内存就无法归还系统。因为内存泄漏属于程序运行中的问题,无法通过编译来识别,所以只能在程序运行过程中来判别和诊断。