티스토리 뷰

CS

Stack Overflow

DEVELON 2024. 8. 7. 14:04
반응형

스택 메모리의 한계를 초과할 때 발생하는 오류입니다!

특히 재귀 함수에서 흔히 발생합니다.

재귀는 많은 알고리즘과 자료구조에서 필수적인 개념이지만, 스택 메모리에 의존하기 때문에 무제한 호출은 스택 오버플로우를 초래할 수 있습니다.

 

원인

  • 무한 재귀 호출: 재귀 함수가 종료 조건을 만족하지 못해 계속해서 자기 자신을 호출하는 경우
func faultyFactorial(_ n: Int) -> Int {
    return n * faultyFactorial(n - 1) // 종료 조건이 없어 무한 재귀 발생
}

// 스택 오버플로우 발생
faultyFactorial(5)
  • 과도한 메모리 할당: 스택에 너무 많은 데이터를 할당하면 스택 메모리가 부족할 수 있습니다.
  • 깊이가 너무 깊을 때: 함수가 계속 다른 함수를 호출하여 중첩된 함수 호출이 너무 많이 쌓이면 발생할 수 있습니다.

 

관리

스택 오버플로우를 예방하려면 재귀 호출을 제어하는 전략이 필요합니다.

  • Base case 확립: 재귀 함수의 중단 조건을 정확하게 설정하는 것이 필수적입니다. 이는 함수 호출의 깊이를 제한하고 스택 오버플로우를 방지하는 첫걸음입니다.
func factorial(_ n: Int) -> Int {
    if n == 0 {
        return 1 // 종료 조건: 0! = 1
    } else {
        return n * factorial(n - 1) // 재귀 호출
    }
}

factorial(5) // 출력: 120

 

  • 꼬리 재귀 최적화 활용: 이는 재귀 호출을 일련의 반복문으로 변환하는 것과 비슷하여, 스택 공간을 크게 절약할 수 있습니다.
func tailRecursiveFactorial(_ n: Int, _ accumulator: Int = 1) -> Int {
    if n == 0 {
        return accumulator
    }
    return tailRecursiveFactorial(n - 1, n * accumulator)
}

tailRecursiveFactorial(5) // 출력: 120

 

  • 반복문 사용: 가능한 경우에는 재귀 대신 반복문을 사용하는 것이 안전합니다. 반복문은 스택 메모리를 사용하지 않습니다.
func iterativeFactorial(_ n: Int) -> Int {
    var result = 1
    for i in 1...n {
        result *= i
    }
    return result
}

iterativeFactorial(5) // 출력: 120

 

 

 

 

스택 오버플로우가 발생하면 프로그램은 강제 종료되므로, 주의 깊에게 처리해야 합니다!

반응형

'CS' 카테고리의 다른 글

LLVM  (0) 2024.03.22