본문 바로가기
프로그래밍/운영체제

프로세스에서 스택 메모리의 역할

by argentdarae 2025. 4. 9.
반응형

운영체제는 프로세스를 메모리에 적재할 때, 코드 영역(code), 데이터 영역(data), 힙 영역(heap), 스택 영역(stack) 등으로 나누어 관리한다

 

이 중 스택 영역은 함수 호출 시 생성되는 스택 프레임(stack frame)을 저장하는 공간으로, 주로 지역 변수, 매개변수, 반환 주소 등의 데이터를 관리하는 데 사용된다

출처: Wikipedia

스택 메모리 구조와 동작 방식

스택은 후입선출(LIFO, Last-In First-Out) 구조로 동작하며, 각 함수 호출 시마다 새로운 스택 프레임이 생성되고, 함수가 종료되면 해당 프레임이 제거된다

 

이렇게 동작함으로써 프로세스는 함수 호출의 흐름을 추적하고, 호출된 함수의 상태를 보존할 수 있다

 

스택 메모리의 존재 의의

스택은 단순한 저장 공간이 아니라, 함수 호출의 흐름을 자동으로 관리하고 지역적인 메모리 사용을 효율적으로 처리하기 위해 설계된 구조다

함수가 호출될 때마다 별도의 저장 공간을 만들고, 종료되면 정리하는 작업을 수동으로 처리하는 것은 매우 복잡하고 오류 가능성이 높다

스택은 이러한 함수 호출 구조를  후입선출(LIFO) 구조를 통해 가장 마지막에 호출된 함수가 먼저 종료되도록 보장한다

또한, 스택은 각 함수 호출 시 생기는 지역 변수와 반환 주소, 매개변수 등의 정보를 한 프레임 단위로 묶어 저장함으로써, 동일한 코드가 여러 번 호출되더라도 독립적인 실행 흐름을 유지할 수 있도록 한다

이러한 구조 덕분에 C와 같은 언어는 재귀 호출, 중첩 함수, 스택 기반 함수 호출 모델 등을 안정적으로 구현할 수 있다

 

스택 프레임(Stack Frame)

함수 호출 시 생성되는 메모리 블록이다

 

스택 프레임 메모리에 저장되는 데이터는 다음과 같다

  • 지역 변수
  • 매개변수
  • 반환 주소
  • 이전 프레임 포인터(EBP)

각 함수는 자신만의 스택 프레임을 가지며, 함수가 종료되면 해당 프레임은 스택에서 제거된다

 

스택 관련 레지스터

ESP (Stack Pointer)

  • 현재 스택의 최상단(top)을 가리키는 레지스터
  • 스택에 값이 push되면 감소하고, pop되면 증가

EBP (Base Pointer)

  • 현재 함수의 스택 프레임의 기준점
  • 지역 변수나 매개변수를 접근할 때 기준 주소 역할
  • 함수 호출 시 이전 함수의 EBP를 저장하고, 함수 종료 시 복원됨

 

스택 메모리 사용 예시

#include <stdio.h>

void function_a(int a) 
{
    int local_var_a = a;
    printf("function_a: local_var_a = %d\n", local_var_a);
}

void function_b(int b) 
{
    int local_var_b = b;
    function_a(local_var_b);
    printf("function_b: local_var_b = %d\n", local_var_b);
}

int main(void) 
{
    int x = 10;
    function_b(x);
    printf("main: x = %d\n", x);
    return 0;
}

 

함수 호출 시 스택 프레임의 흐름은 다음과 같다

  1. main 호출 → 스택 프레임 생성 (지역 변수 x)
  2. function_b 호출 → 새로운 스택 프레임 생성 (local_var_b)
  3. function_a 호출 → 또 다른 스택 프레임 생성 (local_var_a)
  4. function_a 종료 → 해당 스택 프레임 제거
  5. function_b 종료 → 스택 프레임 제거
  6. main 종료 → 프로그램 종료

 

스택 오버플로우와 주의점

스택은 프로세스마다 한정된 크기로 할당되므로, 무한 재귀 호출이나 과도한 지역 변수 사용으로 스택 오버플로우(Stack Overflow)가 발생할 수 있다

#include <stdio.h>

void recursive_function(int count) 
{
    int arr[1000];  // 큰 지역 배열로 스택 공간 소모
    printf("Recursive call: %d\n", count);
    recursive_function(count + 1);  // 종료 조건 없는 재귀
}

int main(void) 
{
    recursive_function(1);
    return 0;
}


// 실행 결과
Recursive call: 1
Recursive call: 2
...
Segmentation fault (스택 오버플로우)

 

이 오류는 스택 포인터(ESP)가 유효한 스택 메모리 범위를 벗어났기 때문에 운영체제에 의해 차단된 것이며, 이는 대표적인 런타임 오류 중 하나다


Reference

Operating Systems: Three Easy Pieces (OSTEP)

=> Chapter 14: Memory API, Chapter 16: Segmentation

Call Stack - Wikipedia

Stack-based memory allocation - Wikipedia

Stack buffer overflow - Wikipedia