OPEN HYPER STEP
← 목록으로 (화이트햇 보안)
SECURITY · 89 / 96
security
CHAPTER 89 / 96
읽기 약 2
FUNCTION

스택과 힙: 메모리 영역 이해


핵심 개념

코드/데이터/BSS/힙/스택 5개 영역 — 지역 변수(스택) vs malloc(힙). 스택 오버플로우의 원리.

본문

프로세스 메모리 5개 영역

📋 코드 (15줄)
┌──────────────────┐
│   스택 (Stack)    │  ← 지역 변수, 함수 호출
├──────────────────┤
│       ↓          │
│                  │
│       ↑          │
├──────────────────┤
│    힙 (Heap)      │  ← malloc 동적 할당
├──────────────────┤
│   BSS Segment    │  ← 초기화 안 된 전역
├──────────────────┤
│   Data Segment   │  ← 초기화된 전역/static
├──────────────────┤
│   Code (Text)    │  ← 컴파일된 함수 코드
└──────────────────┘  낮은 주소

각 영역의 변수

C📋 코드 (17줄)
#include <stdio.h>
#include <stdlib.h>

int global_init = 100;       // Data
int global_uninit;            // BSS

void func(void) {
    int local = 1;            // Stack
    static int s = 5;         // Data (한 번만 초기화)
    int *heap = malloc(16);   // Heap
    free(heap);
}

int main(void) {
    func();
    return 0;
}

스택 — 함수 호출 프레임

C📋 코드 (24줄)
#include <stdio.h>

void inner(void) {
    int x = 10;
    printf("inner: x = %p\n", (void*)&x);
}

void outer(void) {
    int y = 20;
    printf("outer: y = %p\n", (void*)&y);
    inner();
}

int main(void) {
    int z = 30;
    printf("main: z = %p\n", (void*)&z);
    outer();
    return 0;
}

// 출력 (스택은 보통 높은 주소→낮은 주소로 자람):
// main:  z = 0x7ffd1238
// outer: y = 0x7ffd1218   ← 더 낮은 주소
// inner: x = 0x7ffd11f8   ← 더 낮은 주소

스택 프레임 시각화

📋 코드 (22줄)
[main 호출]
스택:
┌─────────────┐
│  return addr │ ← main 호출자의 다음 명령
│  saved %rbp  │ ← 이전 프레임 포인터
│  z = 30      │
└─────────────┘

[outer 호출]
스택:
┌─────────────┐
│  ...main 데이터... │
├─────────────┤
│  return addr │ ← main 함수 안의 다음 명령
│  saved %rbp  │
│  y = 20      │
└─────────────┘

[함수 종료]
- return addr 사용해 호출자로 복귀
- 스택 포인터 복구
- 지역 변수 사라짐

스택 오버플로우 — 무한 재귀

C📋 코드 (14줄)
#include <stdio.h>

void recursive(int depth) {
    char buffer[1024];  // 1KB씩 스택 사용
    printf("depth = %d\n", depth);
    recursive(depth + 1);  // ⚠️ 종료 조건 없음
}

int main(void) {
    recursive(0);
    // 출력: depth=0, 1, 2, ... 수천 번 후 SIGSEGV
    // 스택 한도 (보통 8MB) 초과 → 세그폴트
    return 0;
}

힙 — 동적 할당

C📋 코드 (32줄)
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    // 런타임에 크기 결정
    int n;
    printf("배열 크기 입력: ");
    if (scanf("%d", &n) != 1 || n <= 0) {
        return 1;
    }

    // 힙에 할당
    int *arr = malloc(n * sizeof(int));
    if (arr == NULL) {
        fprintf(stderr, "메모리 부족\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        arr[i] = i * 10;
    }

    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr);  // ⚠️ 반드시 free
    arr = NULL; // 다시 사용 방지

    return 0;
}

스택 vs 힙 비교

📋 코드 (9줄)
| 측면 | 스택 | 힙 |
|---|---|---|
| 할당 | 자동 (함수 호출 시) | 수동 (malloc) |
| 해제 | 자동 (함수 종료) | 수동 (free) |
| 속도 | 매우 빠름 | 느림 |
| 크기 | 작음 (보통 1~8MB) | 큼 (수 GB) |
| 수명 | 함수 범위 | 명시적 free까지 |
| 수정 | 컴파일 시 결정 | 런타임 가능 |
| 단편화 | 없음 | 있음 |

메모리 영역 확인

C📋 코드 (23줄)
#include <stdio.h>
#include <stdlib.h>

int gi = 1;        // Data
int gu;            // BSS
const int gc = 5;  // Read-only

int main(void) {
    int local = 10;        // Stack
    static int s = 20;     // Data
    int *h = malloc(16);   // Heap

    printf("Code (main):    %p\n", (void*)main);
    printf("Read-only (gc): %p\n", (void*)&gc);
    printf("Data (gi):      %p\n", (void*)&gi);
    printf("BSS (gu):       %p\n", (void*)&gu);
    printf("Static (s):     %p\n", (void*)&s);
    printf("Heap (h):       %p\n", (void*)h);
    printf("Stack (local):  %p\n", (void*)&local);

    free(h);
    return 0;
}

다음 챕터

CH.6 "malloc과 free" — 동적 메모리의 전체 생명 주기.


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 C 코드의 변수 사용을 분석해서
스택/힙 적절성과 메모리 폭주 가능성을
보고해줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

한국 임베디드 시스템(스택 64KB)
메모리 관리 사례 5가지를 비교해줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 C 코드에서 큰 지역 변수 + 깊은
재귀를 자동 탐지해서 힙 변환 가이드를
만들어줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 GCC stack-protector 옵션과
실무 활용 트렌드를 솔직히 알려줘.

⭐ 이것만 기억하세요
스택과 힙: 메모리 영역 이해 이 3가지만 확실히 잡으세요
1.5개 메모리 영역: Code/Data/BSS/Heap/Stack — 변수의 위치가 수명·크기·속도 결정
2.스택은 빠르고 자동 (함수 범위), 힙은 느리고 수동 (명시적 free 필요)
3.다음 챕터 CH.6에서 malloc/free 동적 메모리 관리의 전체 생명 주기


공유하기
진행도 89 / 96