谈谈你对堆栈溢出的理解?

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/conconbenben/article/details/102492520

        工作了这么多年,不论是换工作还是面试求职者,关于堆栈问题不少,和同事面试一个求职者的时候,同事出了这么一个问题考问应聘者,谈谈对堆栈溢出的理解。这个问题也是几年前某大厂考我的一个问题,印象比较深,所以在这里我就谈谈我对堆栈溢出的理解。

        首先要搞清楚什么是堆栈?

       堆栈是一个在计算机科学中经常使用的抽象数据类型。堆栈具有后进先出的特性。堆栈中定义了一些操作,其中push和pop是两个最典型的操作,push操作在堆栈的顶部加入一个元素。pop操作相反,在堆栈顶部移去一个元素,并将堆栈的大小减1。

        堆栈溢出就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界。常指调用堆栈溢出,本质上一种数据结构的满溢情况。堆栈溢出可以理解为两个方面:堆溢出和栈溢出。

        堆,很容易让我联想到内存堆。​所以堆溢出可以理解为内存溢出(OutOfMemory),比如不断的new 一个对象,一直创建新的对象,而不进行释放,最终导致内存超出虚拟机分配的内存空间。

        如下代码展示的内存溢出:

import java.util.ArrayList;
import java.util.List;
​public class OutOfMemoryTest {
    public static void main(String[] args) {
        List<int[]> list = new ArrayList<int[]>();
        for (; ; ) {
            int[] tmp = new int[1000000];
            list.add(tmp);
        }
    }
}

         运行报错:

        原因是for死循环一直在new整形数组并add到list中,最终导致内存不足出现异常。

        栈,很容易联想到到方法调用栈。栈溢出,可以理解为方法调用栈溢出(StackOverflow),如:一次函数调用中,栈中将被依次压入:参数,返回地址等,而方法如果递归比较深或进去死循环,就会导致栈溢出。如下:

public class StackOverflowTest {
    public static void main(String[] args) {
        method();
    }
​
    public static void method() {
        method();
    }
}

        运行报错如下:

        原因是method一直在调用自身方法,无法退出该方法,导致方法栈溢出。

解决办法:

        堆溢出(OutOfMemory),最直接的是通过增大堆内存,但demo中死循环开辟内存多大的内存也无法满足内存需要,所以优化内存分配以及及时回收内存才是解决此类异常的首先。栈溢出(StackOverflow),就是需要处理方法递归调用时正确处理递归结束的条件。

                                                

猜你喜欢

转载自blog.csdn.net/conconbenben/article/details/102492520