포인터와 메모리

동적 메모리 관리

Compile 시점에 size나 lifetime을 정할 수 없을 때 dynamic storage가 필요합니다.

동적 메모리 관리이란?

Compile 시점에 size나 lifetime을 정할 수 없을 때 dynamic storage가 필요합니다.

Runtime 크기 배열을 할당하고 안전하게 해제합니다.

중요한 점

  • 포인터는 살아 있는 호환 객체를 가리키거나 null이어야 합니다.
  • 소유한 allocation은 정확히 한 번 해제하세요.
  • 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는 malloc/calloc과 free를 짝지어 실패를 확인합니다. std::vector는 소유와 해제를 자동화하고 exception에도 안전합니다.

C

Ownership과 cleanup은 개발자가 지켜야 하는 규칙입니다.

C++

Container와 RAII가 ownership과 cleanup을 lifetime에 연결합니다.

연습 문제

두 버전을 실행하고 수정하여 각 언어의 보장을 관찰하세요.

  • null과 할당 실패를 테스트하세요.
  • AddressSanitizer와 UndefinedBehaviorSanitizer를 실행하세요.
  • 각 pointer의 ownership을 문서화하세요.