inblog logo
|
heo-gom
    java

    스택 오버플로우(Stack Overflow)

    허성재's avatar
    허성재
    Aug 13, 2024
    스택 오버플로우(Stack Overflow)
    Contents
    1. Stack Overflow의 뜻2. Stack Overflow의 대표적 원인과 해결 방법
     
    정말 유명한 개발자들의 사이트인 스택 오버플로우의 뜻을 알아보자.
     

    1. Stack Overflow의 뜻

    Stack Overflow는 프로그램 실행 중에 호출 스택(call stack)이 허용된 크기를 초과할 때 발생하는 오류입니다. 호출 스택은 함수나 메서드 호출 시 해당 함수의 매개변수, 복귀 주소 등을 저장하는 메모리 영역입니다. 메서드가 너무 깊게 중첩되거나 재귀 호출이 끝나지 않으면 스택 메모리가 가득 차서 더 이상 데이터를 저장할 수 없는 상황이 발생하며, 이때 StackOverflowError가 발생합니다.

    2. Stack Overflow의 대표적 원인과 해결 방법

    2.1 원인: 무한 재귀 호출 (Infinite Recursion)

    무한 재귀 호출은 메서드가 끝없이 자기 자신을 호출하는 경우입니다. 이러한 경우, 호출 스택이 계속해서 쌓이다가 결국 스택 메모리가 가득 차서 StackOverflowError가 발생합니다.
    Java 예제:
    public class StackOverflowExample { public static void recursiveMethod() { recursiveMethod(); // 종료 조건 없이 자기 자신을 계속 호출 } public static void main(String[] args) { recursiveMethod(); // StackOverflowError 발생 } }
    위 코드에서는 recursiveMethod()가 자기 자신을 계속 호출하면서 무한 루프에 빠집니다. 이는 스택 메모리를 고갈시켜 StackOverflowError를 일으킵니다.
     

    해결 방법: 종료 조건 추가 (Base Case)

    재귀 호출에 대한 종료 조건을 추가하여 스택 오버플로우를 방지할 수 있습니다. 종료 조건이 있으면 재귀 호출이 일정 조건에서 멈추기 때문에 호출 스택이 더 이상 쌓이지 않습니다.
    Java 예제:
    public class StackOverflowSolution { public static void recursiveMethod(int n) { if (n == 0) { // 종료 조건 설정 return; // 재귀 호출 종료 } recursiveMethod(n - 1); // 재귀 호출 } public static void main(String[] args) { recursiveMethod(5); // 안전한 재귀 호출 } }
    이 코드에서는 n이 0이 되면 재귀 호출이 종료됩니다. 이렇게 종료 조건이 추가되면 스택 오버플로우가 발생하지 않습니다.

    2.2 원인: 과도한 재귀 깊이 (Excessive Recursion Depth)

    재귀 호출이 종료 조건을 가지고 있더라도, 재귀 호출의 깊이가 너무 깊으면 스택 메모리가 여전히 초과될 수 있습니다. 이는 특히 재귀 깊이가 매우 큰 경우에 발생합니다.
    Java 예제:
    public class ExcessiveRecursionExample { public static void deepRecursion(int n) { if (n == 0) { return; } deepRecursion(n - 1); // 재귀 호출 } public static void main(String[] args) { deepRecursion(100000); // 큰 깊이의 재귀 호출 -> StackOverflowError 발생 가능 } }

    해결 방법: 반복문으로 리팩토링 (Refactoring to Iteration)

    재귀 호출 대신 반복문을 사용하여 문제를 해결할 수 있습니다. 반복문은 재귀 호출처럼 호출 스택을 사용하지 않으므로, 스택 오버플로우의 위험이 없습니다.
    Java 예제:
    public class IterativeSolution { public static void iterativeMethod(int n) { while (n > 0) { n--; } } public static void main(String[] args) { iterativeMethod(100000); // StackOverflowError 발생하지 않음 } }
    이 코드에서는 반복문을 사용하여 재귀 호출의 위험을 피하고, 더 큰 입력 값도 처리할 수 있습니다.
     

    2.3 꼬리 재귀 최적화 (Tail Recursion Optimization)

    • Tail Recursion은 재귀 호출이 함수의 마지막 동작으로 이루어지는 경우입니다. 일부 컴파일러나 런타임에서는 이러한 꼬리 재귀를 최적화하여 스택 프레임을 재사용함으로써 스택 오버플로우를 방지할 수 있습니다.
    • Java에서는 기본적으로 꼬리 재귀 최적화(Tail Call Optimization, TCO)가 지원되지 않지만, 이 패턴을 활용할 수 있는 경우, 알고리즘을 다른 언어로 구현하거나, 꼬리 재귀 최적화가 가능한 런타임 환경에서 실행할 수도 있습니다.
    꼬리 재귀 예제:
    public class TailRecursionExample { public static int tailRecursiveMethod(int n, int result) { if (n == 0) { return result; // 종료 조건 } return tailRecursiveMethod(n - 1, result * n); // 마지막 호출로 꼬리 재귀 } public static void main(String[] args) { System.out.println(tailRecursiveMethod(5, 1)); // 결과: 120 } }
    위의 예제에서는 tailRecursiveMethod가 꼬리 재귀를 사용하고 있으나, Java에서 자동으로 최적화되지는 않습니다. 하지만 일부 다른 언어에서는 이러한 패턴을 최적화하여 스택 오버플로우를 방지할 수 있습니다.

    2.4 스택 크기 조정

    • JVM(Java Virtual Machine) 스택 크기 조정: Java에서는 JVM의 스택 크기를 조정하여 스택 오버플로우를 방지할 수 있습니다. 그러나 이것은 임시적인 해결책에 불과하며, 근본적인 문제를 해결하지는 않습니다.
    JVM 스택 크기 조정 예제:
    • 커맨드 라인에서 Xss 옵션을 사용하여 스택 크기를 늘릴 수 있습니다.
    java -Xss2m YourClassName
    • 이 옵션은 기본 스택 크기를 초과하는 큰 재귀나 깊은 함수 호출을 처리할 때 유용할 수 있습니다. 하지만 스택 크기를 무작정 늘리는 것은 메모리 낭비로 이어질 수 있으며, 근본적인 문제를 해결하는 방법은 아닙니다.

    2.5 재귀 대신 데이터 구조 사용

    • 재귀 호출을 데이터 구조(예: 스택 자료구조)를 사용하여 구현할 수 있습니다. 이렇게 하면 스택 오버플로우를 피하면서 재귀 알고리즘의 논리를 유지할 수 있습니다.
    Java에서 스택을 사용한 예제:
    import java.util.Stack; public class StackBasedSolution { public static void iterativeFactorial(int n) { Stack<Integer> stack = new Stack<>(); int result = 1; while (n > 0) { stack.push(n--); } while (!stack.isEmpty()) { result *= stack.pop(); } System.out.println(result); // 결과 출력 } public static void main(String[] args) { iterativeFactorial(5); // 결과: 120 } }
    이 방법은 호출 스택이 아닌 별도의 스택 객체를 사용하여 스택 오버플로우 문제를 해결합니다.
     
    Share article
    Contents
    1. Stack Overflow의 뜻2. Stack Overflow의 대표적 원인과 해결 방법

    heo-gom

    RSS·Powered by Inblog