이런 분들이 찾고 있어요
이 레슨과 관련된 학습 키워드
코드를 읽고 설명하면, 합격합니다
이 레슨과 관련된 학습 키워드
C++ 프로그래밍 — 성능과 추상화의 균형 → 모던 C++
new로 힙 메모리를 할당하고 delete로 해제하는 raw 포인터 관리는 세 가지 치명적 버그를 만든다:delete를 빼먹으면 프로그램이 끝날 때까지 메모리가 반환되지 않음delete → 힙 구조 손상 → 정의되지 않은 동작(UB)1# C++ 의사코드 (Python 문법 아님 — 개념 설명용)💡2# void process() {💡3# Widget* w = new Widget(); // 힙 할당💡4# w->doWork(); // ← 여기서 예외 발생!💡5# delete w; // ← 영원히 실행되지 않음 → 누수💡6# }💡오늘은 왜 스마트 포인터가 필요한지, 그 근본 이유를 살펴보겠습니다.
C++에서 new와 delete로 메모리를 직접 관리하면 치명적인 버그가 세 종류 생깁니다.
그림 상단 가운데 제목을 보시면, Raw 포인터의 3대 위험이라고 나와 있죠.
첫 번째는 메모리 누수입니다.
delete를 빠뜨리면 메모리가 절대로 반환되지 않습니다.
그림 왼쪽 박스를 보세요.
1시간, 12시간, 24시간 지날수록 메모리가 쌓이다가 결국 오오엠 크래시가 납니다.
서버 프로세스가 며칠만 돌면 수 기가바이트가 누적되는 거죠.
두 번째는 이중 해제 문제입니다.
같은 포인터를 두 번 delete하면 힙 구조가 손상됩니다.
가운데 박스를 보시면, delete를 두 번 날린 뒤 힙 구조 손상, 즉 유비가 발생합니다.
정의되지 않은 동작이라 디버깅이 극히 어렵습니다.
세 번째 댕글링 포인터는 오른쪽 박스를 보시면 바로 이해됩니다.
해제된 메모리를 역참조하면 쓰레기 값이 읽히거나 크래시가 납니다.
그런데 조심히 코딩하면 되지 않냐고 생각할 수 있어요.
예외 안전성 문제가 바로 이 생각을 무너뜨립니다.
doWork 함수에서 예외가 발생하는 순간 캐치 블록으로 점프합니다.
그러면 아래 delete 라인은 영원히 실행되지 않아요.
더 근본적인 문제는 소유권이 코드에 명시되지 않는다는 점입니다.
함수에 포인터를 넘길 때, 누가 해제해야 하는지 알 수가 없죠.
C++ 11은 라이아이 원칙으로 이 문제를 해결했습니다.
라이아이란 자원 획득을 객체 생성에, 해제를 소멸에 묶는 원칙입니다.
스코프를 벗어나면 소멸자가 자동 호출되니, 예외가 발생해도 해제가 보장됩니다.
그림 하단을 보시면 세 가지 스마트 포인터가 정리돼 있습니다.
unique_ptr은 단독 소유 방식으로, 복사가 불가능하고 이동만 됩니다.
오버헤드가 제로라 기본 선택으로 권장됩니다.
shared_ptr은 공유 소유 방식으로, 참조 카운팅을 써서 마지막 소유자가 해제합니다.
weak_ptr은 비소유 관찰자로, 순환 참조를 방지할 때 shared_ptr과 함께 씁니다.
결국 소유권이란 자원을 누가 해제할 것인가에 대한 컴파일 타임 계약입니다.
스마트 포인터는 이 계약을 타입 시스템으로 강제하는 도구라고 정리할 수 있습니다.