什么是栈?
栈:栈是一种计算机系统中的数据结构,它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶。
如下图所示:
需要读数据的时候从栈顶开始弹出数据,最后一个数据被第一个读出来,是一种特殊的线性表。
栈的操作常用的有:进栈(PUSH),出栈(POP)。
1.进栈(PUSH)
PUSH:将目标内存推入栈顶。
2.出栈(POP)
POP:从栈顶中移除目标。
那么,栈是用来做什么的呢?
我们都知道内存是用来存储数据的,栈也不例外,栈用来存储程序的局部数据。
局部数据是指在函数内部定义的数据,例如:在方法内部定义的变量、参数、结构体、数组、对象、引用等,它们都要保存到栈中。
什么是栈溢出?
对每个程序来说,栈能使用的内存是有限的,这在编译时就已经决定了,程序运行期间不能再改变。
如果程序使用的栈内存超出最大值,就会发生栈溢出(Stack Overflow)错误,程序就崩溃了。
这个就像木桶里的水,木桶的容量有限,水满了自然会溢出来,如下图所示:
栈溢出的原因?
最常见的就是递归,每次递归就相当于调用一个函数,函数每次被调用时都会将局部数据:在方法定义的变量、参数、数组、对象等等放入栈中。
递归过程的局部变量过多、递归深度过大,是造成系统栈溢出的原因,特别是递归列循环时,很容易就导致栈溢出了。
比如:递归500次,就会将500份这样的数据放入栈中,这些数据占用的内存直到整个递归结束才会被释放,在递归过程中只会累加,不会释放。
除此之外,还有死循环:不断的new 对象,一直创建新的对象,也很容易就导致栈溢出。
栈溢出的解决方案
- 减少栈空间的需求,不要定义占用内存较多的变量,因为栈的空间大小是有限的,一般就几兆,可以从堆空间分配内存;
- 函数参数中不要传递:大型结构、联合对象,应该使用引用或指针作为函数参数;
- 减少函数调用层次,慎用递归函数,例如A->B->C->A环式调用,这样可以有效的避免栈溢出。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》