소멸자 패턴
Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 13번째.
malloc으로 생성된 모든 객체는 결국 해제되어야 합니다. 할당을 처리하기 위해 create_ 함수를 작성한 것과 마찬가지로, 정리를 처리하기 위해 free_ 함수를 작성합니다. 이것이 소멸자 패턴(destructor pattern)입니다.
핵심적인 통찰은 해제(freeing)가 할당(allocation)의 역순으로 일어나야 한다는 것입니다. 만약 생성자(constructor)가 내부 멤버를 먼저 할당한 다음 구조체(struct) 자체를 할당했다면, 소멸자(destructor)는 구조체의 멤버를 먼저 해제한 다음 구조체를 해제해야 합니다:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // 안전 확인
free(p->name); // 내부 멤버를 먼저 해제
free(p); // 그 다음 구조체 자체를 해제
}
시작 부분의 NULL 검사는 누군가 실수로 유효하지 않은 포인터를 전달할 경우 발생하는 충돌을 방지합니다. 내부의 name 문자열을 해제한 후, 구조체 자체를 해제합니다. 만약 p를 먼저 해제하면 p->name에 접근할 수 없게 되어 메모리 누수가 발생합니다.
소멸자를 사용하는 것은 간단합니다:
Person *alice = create_person("Alice", 30);
// ... alice 사용 ...
free_person(alice); // 작업이 끝나면 정리
이 패턴은 모든 메모리가 적절하게 해제되도록 보장합니다. 이것이 없으면, 생성하는 모든 객체는 프로그램의 메모리가 부족해질 때까지 메모리 누수를 일으킬 것입니다.
챌린지
쉬움생성 및 소멸이라는 전체 객체 수명 주기를 보여주는 Movie 모듈을 만들어 보겠습니다. 할당된 모든 메모리를 올바른 순서로 적절하게 정리하는 소멸자 함수를 작성하는 연습을 하게 됩니다.
세 개의 파일을 생성합니다:
movie.h: 두 개의 멤버char *title(동적으로 할당된 문자열)과int year를 가진Movie구조체를 선언합니다. 제목과 연도를 인자로 받는 생성자create_movie와 Movie 포인터를 인자로 받는 소멸자free_movie를 모두 선언합니다.MOVIE_H심볼을 사용하여 include guard를 사용하세요.movie.c: 두 함수를 구현합니다. 생성자는 구조체와 그 제목 문자열을 위한 메모리를 할당해야 합니다(널 종료 문자를 잊지 마세요). 소멸자는 할당의 역순으로 메모리를 해제해야 합니다. 즉, 내부의title문자열을 먼저 해제한 다음 구조체 자체를 해제해야 합니다. 안전을 위해 소멸자 시작 부분에 NULL 체크를 포함하세요.main.c: 영화를 생성하고, 정보를 표시한 다음, 메모리를 적절하게 정리합니다.
두 개의 입력을 받습니다: 영화 제목(문자열)과 개봉 연도(정수).
메인 파일에서 create_movie를 사용하여 새 영화를 생성하고, 정보를 출력한 다음, free_movie를 호출하여 모든 메모리를 해제합니다. 해제한 후에는 확인 메시지를 출력합니다.
출력은 다음 형식으로 하세요:
Movie: {title} ({year})
Memory freed예를 들어, 입력이 Inception과 2010인 경우 출력은 다음과 같습니다:
Movie: Inception (2010)
Memory freed기억하세요: 적절한 소멸자의 핵심은 역순으로 해제하는 것입니다. 생성자가 먼저 할당한 것은 마지막에 해제되고, 마지막에 할당한 것은 가장 먼저 해제됩니다.
치트 시트
malloc으로 생성된 모든 객체는 소멸자 함수를 사용하여 해제해야 합니다. 소멸자는 할당된 **역순**으로 메모리를 해제하는 패턴을 따릅니다.
기본적인 소멸자 구조:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // Safety check
free(p->name); // Free internal members first
free(p); // Then free the struct itself
}
주요 원칙:
- 충돌을 방지하기 위해 항상 시작 부분에
NULL체크를 포함하세요. - 구조체 자체를 해제하기 전에 내부 멤버들을 먼저 해제하세요.
- 구조체를 먼저 해제하면 멤버에 대한 접근 권한을 잃게 되어 메모리 누수가 발생합니다.
사용 예시:
Person *alice = create_person("Alice", 30);
// ... use alice ...
free_person(alice); // Clean up when done
직접 해보기
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// 입력 읽기
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: create_movie를 사용하여 영화 생성
// TODO: 다음 형식으로 영화 정보 출력:
// Movie: {title} ({year})
// TODO: free_movie를 사용하여 영화 메모리 해제
// TODO: "Memory freed" 출력
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.