본문 바로가기

학습 기록 (Learning Logs)/Today I Learned

📘17. 메모리 관리

1. 메모리 공간의 종류

📌 1. 스택 메모리 (Stack Memory)

자동 메모리 (automatic memory) 함수 안에서 선언된 지역 변수는 자동으로 할당 및 해제
관리 주체 컴파일러가 처리함 – 프로그래머가 직접 신경 쓸 필요 없음
사용 예 int x; 같은 선언문은 스택에 메모리를 할당
메모리 해제 함수 호출이 끝나면 자동으로 해제
주의점 함수가 끝나면 사라지므로, 반환 후에도 필요한 값은 스택에 두면 안 됨

 

📌 2. 힙 메모리 (Heap Memory)

동적 메모리 (dynamic memory) 실행 중 malloc() 등을 통해 직접 명시적으로 할당
관리 주체 프로그래머가 직접 할당과 해제를 책임져야 함
사용 예 int *x = (int *) malloc(sizeof(int)); – 정수를 위한 힙 메모리 할당
메모리 해제 사용 후 반드시 free(x);로 해제해줘야 함
위험성 잘못 사용하면 메모리 누수, 이중 해제, 미해제 등 버그 발생 가능

 

📌 스택 vs 힙 비교 요약

항목 스택
생성 방식 자동 (컴파일러) 수동 (malloc() 등)
해제 시점 함수 종료 시 자동 직접 free() 호출 필요
용도 지역 변수 동적 데이터 저장 (배열, 구조체 등)
속도 빠름 상대적으로 느림
위험성 거의 없음 누수/오류 발생 가능성 있음

 


 

2. malloc() 함수

  • 역할: 힙에서 지정된 바이트 크기만큼 메모리를 동적으로 할당함
  • 반환: 해당 메모리의 포인터를 반환합니다. 할당에 실패하면 NULL을 반환합니다.
  int *ptr = (int *) malloc(sizeof(int));

할당된 메모리는 초기화되지 않으므로, 사용 전에 값을 설정해야 합니다.

 

 

int *x = (int *) malloc(10 * sizeof(int));

malloc()에 전달할 크기는 sizeof()를 사용해서 정확히 계산해야 안전함

sizeof(x)는 포인터 x의 크기이지, x가 가리키는 배열의 크기가 아님
→ 32bit 시스템에서는 4, 64bit에서는 8이 반환됨

 

✅ sizeof()는 함수가 아님 → 컴파일 시간에 계산됨

  • 정적인 타입 정보(예: int, double)에 대해서 컴파일러가 계산해서 숫자로 바꿔 넣음
    → sizeof(double) → 컴파일 타임에 8로 대체됨

3. free() 함수

  • 기능: malloc() 등을 통해 할당된 메모리를 해제하여 메모리 누수를 방지합니다.
  free(ptr);

 

할당되지 않은 메모리나 이미 해제된 메모리를 다시 해제하려고 하면 정의되지 않은 동작이 발생할 수 있으므로 주의해야 합니다.

 


 

4. 흔한 오류와 주의사항

  • 메모리 할당 누락: 사용 전에 메모리를 할당하지 않으면 프로그램이 비정상 종료될 수 있습니다.
  • 할당된 메모리의 해제 누락: 사용이 끝난 메모리를 해제하지 않으면 메모리 누수가 발생할 수 있습니다.
  • 해제된 메모리 접근: 이미 해제된 메모리에 접근하면 정의되지 않은 동작이 발생할 수 있습니다.
  • 잘못된 포인터로 free() 호출: 유효하지 않은 포인터로 free()를 호출하면 프로그램이 비정상 종료될 수 있습니다.