본문 바로가기
개발 노트 (C언어)

Stack Overflow 왜 발생하는가? #스택 #큐

by jjongday 2024. 5. 15.
반응형

Stack Overflow

Stack Overflow는 Stack 영역의 메모리가 지정된 범위를 넘어갈 때 발생한다.


Stack 메모리는 보통 지역 변수가 저장되는 영역이다. 

함수에서 지역 변수를 선언하면 지역 변수는 Stack 메모리에 할당되고 함수를 빠져 나오면 Stack 메모리에서 해제된다. 

하나의 프로그램이 실행 될 때 수 많은 함수를 호출하고 빠져 나오게 되는데 그 때마다 함수에서 사용하는 

지역 변수는 Stack 영역에 할당되고 해제되는 것을 반복하게 되며 그에 따라 사용되는 Stack 영역도 변하게 된다.

  
만약 한 함수에서 너무 큰 지역 변수를 선언하거나 함수를 재귀적으로 무한정 호출하게 되면 Stack Overflow가 발생할 수 있다.
 

Stack Overflow가 발생하면 컴파일러 옵션에서 Stack 영역의 크기를 늘리거나 또는

함수에서 사용하는 지역 변수의 크기를 줄이거나 아니면 지역 변수를 전역 변수로 바꾸어 해결할 수 있다.
 

Visual C++과 같은 PC 컴파일러에서는 디버깅 모드에서 Stack Overflow가 발생하면 Stack Overflow 에러 메세지를 출력하지만 임베디드 시스템에서는 Stack Overflow 에러 메세지를 출력하지 않고 이상 동작하는 경우가 많기 때문에 주의 해야 한다. Stack Overflow는 매우 찾기가 어려운 버그이며, 2009년 발생한 도요타 렉서스 자동차의 급발진 원인이 Stack Overflow 떄문이었다고 한다. ㄷㄷ....
 

자료구조에서 Stack과 비슷한 구조에는 Queue가 있다.


스택(Stack)은 LIFO(Last-In First-Out)이고, 큐(Queue)는 FIFO(First-In First-Out)이다. 

스택(Stack) 은 가장 나중에 들어온 데이터가 가장 먼저 나가는 데이터 구조이고, 

큐(Queue) 는 가장 먼저 들어온 데이터가 가장 먼저 나가는 데이터 구조이다.

아래 그림을 보면 이해할 수 있다.

 

stack overflow 는 언제 발생하는가?

재귀 함수는 스택 오버플로우의 대표적인 사례이다.

재귀함수는 코드의 가독성을 높여주는 프로그래머들이 선호하는 코드이다.

하지만 이는 자칫 프로그램 에러를 발생하는 경우가 발생한다.

어떤 경우에 발생하는지 아래 예시 코드로 알아보자.


전달 받은 임의의 수 범위까지 1부터 곱해 나가면 된다. 

public long calculateFactorial(long number) {
    return number == 1 ? 1 : number * calculateFactorial(number - 1);
    }


함수를 호출할 때 함수의 파라미터, 리턴 값, 복귀 주소 등을 스택에 저장한다.
재귀 함수를 사용하면 호출한 함수가 종료되지 않은 채 새로운 함수를 호출하므로 스택에 메모리가 계속적으로 저장되게 되므로 스택 메모리에 더 이상 가용 메모리가 없을 경우에 스택 오버 플로우가 발생하게 된다.


어떻게 해결할 수 있을까?

함수 호출 시 이전의 호출한 스택 메모리는 종료하면 된다. 이를 꼬리 재귀 라고도 한다. 방법은 간단하다.

다음 함수 호출시 현재 함수의 연산된 결과를 전달하면 된다. 그러면 함수 종료 시 이전 함수의 데이터와 연산할 필요가 없으니 스택 메모리의 이전 함수의 데이터를 따로 저장할 필요가 없다.

public long calculateTailFactorial(long number, long sum) {
    return number == 1 ? sum : calculateTailFactorial(number - 1, number * sum);
}

 

이 처럼 현재 연산을 다음 함수에 결과값으로 도출하기위해 파라미터를 추가하였다. 

그리고 수행을 해보면 정상적으로 결과값을 도출하는 것을 확인할 수 있다.

 

 

출처: https://ko.wikipedia.org/wiki/%EB%B2%84%ED%8D%BC_%EC%98%A4%EB%B2%84%ED%94%8C%EB%A1%9C

https://www.baeldung.com/java-stack-overflow-error

 

반응형

'개발 노트 (C언어)' 카테고리의 다른 글

[C언어] 포인터  (0) 2024.04.24
[C언어] 비트 연산 및 비트 시프트  (0) 2024.04.13