C와 C++의 동적 메모리 관리
이 레슨에서는 실행할 때에야 크기를 알 수 있는 배열을 할당하고, 그 메모리를 안전하게 해제합니다.
소개
동적 메모리는 요소의 개수가 사용자의 입력에 따라 달라지는 경우처럼, 데이터의 크기나 수명을 컴파일할 때 정할 수 없을 때 씁니다. 이 메모리는 프로그램이 실행되는 동안 할당되며, 더 이상 필요하지 않으면 해제해야 합니다.
핵심 정리
- 포인터는 아직 존재하는 올바른 타입의 객체만 가리키거나 null이어야 합니다.
- 할당한 메모리 영역은 정확히 한 번만 해제해야 합니다.
- 어떤 함수가 메모리를 소유(ownership)하는지, 어떤 데이터는 읽기만 하는지(const) 분명히 하세요.
C와 C++ 코드 예제
C
main.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t count = 5;
int *values = calloc(count, sizeof *values);
if (!values) return 1;
for (size_t i = 0; i < count; ++i) values[i] = (int)(i * i);
printf("last=%d\n", values[count - 1]);
free(values);
return 0;
}
last=16
C++
main.cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> values(5);
for (std::size_t i = 0; i < values.size(); ++i) values[i] = static_cast<int>(i * i);
std::cout << "last=" << values.back() << '\n';
}
last=16
C와 C++ 비교
C의 calloc은 정수 5개를 위한 메모리를 할당하고 0으로 초기화합니다. 프로그램은 할당이 실패했는지 확인해야 하고, 마지막에 free를 호출해 메모리를 해제해야 합니다. 그렇지 않으면 메모리 누수(memory leak)가 생깁니다. C++의 std::vector는 메모리를 스스로 관리하며, 예외가 발생하더라도 쓰지 않게 되면 자동으로 해제합니다.
C
메모리의 소유와 해제는 전적으로 프로그래머에게 달려 있습니다.
C++
컨테이너와 RAII가 객체의 수명이 끝날 때 자원을 자동으로 해제합니다.
연습 문제
두 버전을 모두 실행한 다음 코드를 바꿔 보면서 각 언어가 주는 안전성의 차이를 살펴보세요.
- 널 포인터와 메모리 할당 실패 상황으로 테스트해 보세요.
- AddressSanitizer와 UndefinedBehaviorSanitizer로 실행해 메모리 오류를 찾아보세요.
- 어떤 포인터가 메모리를 소유하고 어떤 포인터는 읽기만 하는지 분명히 해 보세요.
챌린지로 연습하기
이 레슨에서 배운 내용으로 실제 문제를 풀어 보세요. 모든 챌린지는 브라우저에서 실행되며 즉시 테스트와 AI 리뷰를 받을 수 있습니다.
모든 챌린지