프로그래밍System C Developer

C에서 스택 메모리 할당의 작동 메커니즘에 대해 자세히 설명해 주세요. 메모리 할당 및 해제는 어떻게 이루어지며, 자동 변수에 대한 제한 사항 및 특징은 무엇이며, 스택의 잘못된 사용은 어떤 오류를 초래합니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

문제의 역사:

스택 메모리는 모든 주요 아키텍처에서 존재합니다. C 언어에서는 자동(로컬) 변수가 스택에 위치하여 동적 힙과 비교하여 메모리 할당 및 해제가 매우 빠릅니다.

문제:

스택의 사용은 크기로 제한되어 있으며, 자동 변수는 블록을 벗어날 때 자동으로 소멸하며, 스택 오버플로우(stack overflow)는 프로그램의 비정상 종료 또는 데이터 손상을 초래합니다.

해결책:

특별한 수정자 없이 함수 내에 선언된 로컬 변수는 스택에 배치됩니다. 이 자동 저장 영역은 함수에 들어갈 때 생성되고 나갈 때 파괴됩니다. 스택의 크기는 제한되어 있으며, 링크 옵션/시스템에서만 변경할 수 있습니다.

코드 예시:

#include <stdio.h> void foo() { int arr[100]; // 스택에 배치됨 for (int i = 0; i < 100; ++i) arr[i] = i; printf("첫 번째 요소: %d\n", arr[0]); } // foo를 벗어날 때 arr이 소멸됨

주요 특징:

  • 스택의 변수 작업은 매우 빠르며 명시적인 해제가 필요하지 않습니다.
  • 스택의 크기는 제한되어 있으며, 큰 객체를 배치하려고 하면 오류가 발생합니다.
  • 지역 변수를 그 가시성 범위를 넘어 참조하는 것은 심각한 오류입니다.

속임수 질문.

주소를 통해 로컬 변수를 반환할 수 있습니까?

아니요, 함수에서 나갈 때 변수가 소멸되므로 결과적으로 "유령 포인터"가 생성되어 정의되지 않은 동작을 초래합니다.

int* bad() { int x = 42; return &x; // 오류: 반환된 포인터가 해제된 스택을 가리킴 }

스택에 큰 배열(예: 1MB)을 배치할 수 있습니까?

대부분의 시스템에서 스택은 제한적입니다(수십에서 수백 KB). 스택에 거대한 배열을 선언하려고 시도하면 스택 오버플로우가 발생합니다.

정적(static) 변수와 자동 변수의 배치에서 차이점은 무엇입니까?

정적 변수(함수 내에서도)는 정적 메모리 영역에 배치되며, 호출 사이에 초기화되지 않고, 자동 변수는 스택에 배치되어 블록을 벗어날 때 소멸됩니다.

일반적인 오류 및 안티 패턴

  • 함수에서 로컬 변수의 주소를 반환하는 것.
  • 크기를 확인하지 않고 스택에 큰 객체를 선언하는 것.
  • 초기화되지 않은 자동 변수를 사용하는 것.

실전 예

부정적 사례

계산을 위한 함수에서 스택에 8192*1024 double 배열을 할당했습니다. 프로그램은 Linux에서 실행 시 SIGSEGV를 받았고, 컴파일에서는 오류가 없었습니다.

장점:

  • 메모리를 명시적으로 해제할 필요가 없습니다.

단점:

  • 제한을 초과했을 때 스택 오버플로우 및 비정상 종료가 발생합니다.

긍정적 사례

대량의 버퍼 작업을 위해 malloc/free를 통한 동적 메모리 할당을 사용했습니다. 스택에는 작은 작업 변수를만 배치했습니다.

장점:

  • 스택 오버플로우 위험이 없습니다.
  • 객체의 생명 주기 및 크기를 더 잘 제어할 수 있습니다.

단점:

  • 메모리를 명시적으로 해제하고 NULL을 확인해야 합니다.