栈溢出和堆溢出


整个内存都是用来存储数据的,栈也不例外。栈用来存储程序的局部数据。

对于C/C++来说,局部数据是指在函数内部定义的数据,例如在函数内部定义的变量、指针、参数、结构体、数组、对象、引用等,它们都要保存到栈中。

与之相对应的,在函数外部定义的变量、指针、对象、结构体、数组等都是全局数据,它们要保存到全局数据区。

而 malloc( )、new、new[ ] 是在程序运行的过程中动态地分配内存,这些内存都位于堆区。

栈为什么会溢出?

对每个程序来说,栈能使用的内存是有限的,一般是 1M~8M,这在编译时就已经决定了,程序运行期间不能再改变。如果程序使用的栈内存超出最大值,就会发生栈溢出(Stack Overflow)错误,程序就崩溃了。
那么,什么情况下才会发生栈溢出呢?

最常见的就是递归。每次递归就相当于调用一个函数,函数每次被调用时都会将局部数据(在函数内部定义的变量、参数、数组、对象等)放入栈中。

递归1000次,就会将1000份这样的数据放入栈中。这些数据占用的内存直到整个递归结束才会被释放,在递归过程中只会累加,不会释放。

如果递归次数过多,并且局部数据也多,那么会使用大量的栈内存,很容易就导致栈溢出了。

在函数内部定义超大数组也会导致栈溢出,例如定义一个 1024 * 1024 的 int 类型的二维数组,就需要 4M 的内存,这在 VS/VC 下就会发生栈溢出。

总结

栈容易溢出是因为栈内存有限,一般就几兆。

栈溢出

栈溢出就是由于递归或循环嵌套层次太多造成的。
1)局部数组过大。当函数内部的数组过大时,有可能导致栈溢出。
2)递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致栈溢出。
3)指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。
栈中分配局部变量空间,堆区是向上增长的用于分配程序员申请的内存空间。具体查内存分配。
栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。
堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

堆溢出

堆是程序员自己创建的,通常来说,导致堆溢出的操作是不断的new 一个对象,一直创建新的对象,但是不销毁。