栈溢出原因及解决方法(3大解决方案详解)

栈溢出原因及解决方法(3大解决方案详解)-mikechen

什么是栈?

栈:栈是一种计算机系统中的数据结构,它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶。

如下图所示:

栈溢出原因及解决方法(3大解决方案详解)-mikechen

需要读数据的时候从栈顶开始弹出数据,最后一个数据被第一个读出来,是一种特殊的线性表。

栈的操作常用的有:进栈(PUSH),出栈(POP)。

1.进栈(PUSH)

PUSH:将目标内存推入栈顶。

2.出栈(POP)

POP:从栈顶中移除目标。

那么,栈是用来做什么的呢?

我们都知道内存是用来存储数据的,栈也不例外,栈用来存储程序的局部数据。

局部数据是指在函数内部定义的数据,例如:在方法内部定义的变量、参数、结构体、数组、对象、引用等,它们都要保存到栈中。

 

什么是栈溢出?

对每个程序来说,栈能使用的内存是有限的,这在编译时就已经决定了,程序运行期间不能再改变。

如果程序使用的栈内存超出最大值,就会发生栈溢出(Stack Overflow)错误,程序就崩溃了。

这个就像木桶里的水,木桶的容量有限,水满了自然会溢出来,如下图所示:

栈溢出原因及解决方法(3大解决方案详解)-mikechen

 

栈溢出的原因?

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

递归过程的局部变量过多、递归深度过大,是造成系统栈溢出的原因,特别是递归列循环时,很容易就导致栈溢出了。

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

除此之外,还有死循环:不断的new 对象,一直创建新的对象,也很容易就导致栈溢出。

 

栈溢出的解决方案

  1. 减少栈空间的需求,不要定义占用内存较多的变量,因为栈的空间大小是有限的,一般就几兆,可以从堆空间分配内存;
  2. 函数参数中不要传递:大型结构、联合对象,应该使用引用或指针作为函数参数;
  3. 减少函数调用层次,慎用递归函数,例如A->B->C->A环式调用,这样可以有效的避免栈溢出。

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法