1. 가상 소멸자(virtual destructor)와 다형적 삭제
난이도 중내 리뷰 · C++
해설 · C++
해설 — 가상 소멸자(virtual destructor)와 다형적 삭제
난이도: 중
답변 프레임워크: 요약 → 핵심 개념 → 단계별 내부 동작 → 흔한 오해·함정 → 면접 포인트
요약
Base 의 소멸자가 virtual 이 아니므로, delete p(p 의 정적 타입 Base*)는 정적 타입
기준으로 ~Base() 만 호출한다. ~Derived() 와 멤버 Resource res_ 의 소멸자가 호출되지
않아 "Resource released" 가 출력되지 않는다 — 이는 표준상 정의되지 않은 동작(UB) 이며
실무에선 리소스 누수(소켓/메모리/핸들)로 나타난다. Base 의 소멸자를 virtual 로 만들면
delete 가 동적 타입을 따라 ~Derived() → 멤버들 → ~Base() 순으로 완전히 소멸한다.
출력 예측
- 현재 코드(비가상 소멸자):
→Base() Resource acquired Derived() ~Base()~Derived()와~Resource()("Resource released")가 누락(UB). - 가상 소멸자로 고친 경우:
Base() Resource acquired Derived() ~Derived() Resource released ~Base()
핵심 개념
- 정적 타입 vs 동적 타입:
p의 정적 타입은Base*, 가리키는 객체의 동적 타입은Derived. delete p의 디스패치: 소멸자가 비가상이면 컴파일러는 정적 타입으로 호출할 소멸자를 결정한다(비다형적). 가상이면 vtable 을 통해 동적 타입의 소멸자로 디스패치한다(다형적).- 소멸 순서: 파생 소멸자 본문 → 파생 멤버(역순) → 기반 소멸자. 비가상이면 이 체인이
~Base()에서 시작·끝나 파생 부분이 통째로 빠진다.
단계별 내부 동작
new Derived():Base()→ 멤버Resource()→Derived()순으로 생성(기반→멤버→파생).delete p(비가상): 컴파일러가Base::~Base를 정적 바인딩으로 호출.Derived의 소멸자와res_소멸자는 실행되지 않음. 그 뒤operator delete(p)로 메모리 해제는 되지만,Derived서브오브젝트가 소멸되지 않은 채 해제됨 → 표준상 UB.- 가상으로 바꾸면:
Base객체에 vptr 이 생기고,delete p는 vtable 의 소멸자 슬롯을 조회해Derived::~Derived를 호출. 이후 멤버~Resource(), 기반~Base()가 순서대로 실행. (컴파일러는 보통 "완전 소멸자/삭제 소멸자" 형태로 vtable 에 넣는다.)
흔한 오해·함정
- "메모리는 해제됐으니 괜찮다" ✗ —
operator delete로 바이트는 회수돼도, 파생/멤버 소멸자가 안 돌면 그들이 들고 있던 소켓/파일/락/힙 버퍼가 누수된다. 게임서버에서 세션 객체가 이렇게 새면 FD/메모리 고갈로 이어진다. - 모든 클래스에 virtual 소멸자를 달면 된다? ✗ — vptr 로 객체 크기 8바이트 증가,
다형적이지 않은 작은 값 타입(POD 류)·표준 레이아웃이 깨질 수 있다. 규칙: 기반 클래스로서
다형적으로 delete 될 수 있으면 virtual 소멸자(또는
protected비가상 소멸자로 기반 포인터 delete 자체를 금지). unique_ptr<Base>면 안전? ✗ —unique_ptr<Base>의 기본 deleter 도delete (Base*)라 동일 문제. (shared_ptr<Base>는 생성 시점의 삭제자를 타입소거로 저장해 예외적으로 파생 소멸자를 부른다 — 단make_shared<Derived>()또는shared_ptr<Base>(new Derived)처럼 생성 시 동적 타입을 알 때만.)
면접 포인트 (예상 질문)
- 비가상 소멸자 기반 포인터 delete 가 왜 UB 이고, 실무에서 어떤 증상(누수)로 나타나나?
virtual을 붙이면 객체 레이아웃이 어떻게 바뀌나(vptr/vtable)? 그 비용은?unique_ptr<Base>와shared_ptr<Base>가 이 상황에서 다르게 동작하는 이유는? 기반 클래스를 다형 삭제 못 하게 막는 대안(protected 비가상 소멸자)은?