1. 개요
이번 장은 자원을 관리하는 법에 대해서 기술하는 챕터이다.
특히 항목 13은 포인터를 사용한뒤 해제하는 방법들을 소개한다.
void f()
{
Investment *pInv = createInvestment();
// 무언가 동작
delete pInv;
}
이러한 코드를 보면 정상적으로 작동한다고 보일 수 있다.
그러나 중간에 있는 주석부분에 다양한 로직이 들어갈 수 있고 그때에 문제가 발생할 가능성이 있다.
2. 문제점과 auto_ptr
저 코드가 정상적으로 delete까지 도달하면 아무런 문제가 없겠지만 그럴것이라는 보장이 절대 없다.
만약 중간에 다른 로직이 추가되어서 delete에 도달하기 전 return을 한다면 memory leak이 발생하게 된다.
혹은 예외등이 발생해도 delete가 실행되지 않을것이다.
물론 프로그래머가 매우 꼼꼼하게 프로그램을 짠다면 이러한 문제는 발생하지 않을지도 모른다.
그러나 코드는 혼자 짜는것도 아니고 많은 사람들이 함께 작업할 일이 많이 있을것인데 그때마다
메모리가 해제되지 않는 모든 상황을 전부 고려해서 만드는 것은 절대로 쉬운일이 아닐것이다.
f함수가 delete로 항상 갈것이라고 절대 신뢰해서는 안된다는 것이다.
책에서는 이럴때 해결책중 하나로 auto_ptr을 설명하는데 auto_ptr은 블럭을 벗어나면 자동으로 메모리를 해제해주는
스마트 포인터를 소개하는데 사실 auto_ptr은 C++98/03에서 쓰이던 스마트 포인터의 초창기 버전이고
C++11 이후엔 사용을 권장하지 않는 상태가 됐고, 결국 C++17에서는 완전히 삭제된 스마트 포인터입니다.
auto_ptr은 자신이 가리키는 대상에 대해 자동으로 delete를 먹여서 어떤 객체를 auto_ptr 2개가 가르킨다면
자원을 2번삭제하게 되는등 안좋은 결과를 낳게 됩니다.
아마도 이러한 불편한점 때문에 삭제되지 않았을까 생각합니다.
3. shared_ptr
책에서는 shared_ptr에 대해서도 설명하고 있습니다.
shared_ptr은 auto_ptr과 다르게 아직 사용되는 스마트 포인터입니다.
shared_ptr은 RCSP의 한 종류입니다.
RCSP는 Reference Counting Smart Poiner의 약자로 자원을 참조하는 외부 객체의 개수를 가지고 있다가 개수가 0이되면
자동으로 자원을 해제하는 포인터 입니다. 마치 garbage collection의 동작과 유사합니다.
그러나 shared_ptr은 서로가 서로를 참조하고 있는 순환참조의 경우 해제가 되지 않는 문제가 발생합니다.
또한 참조 카운팅으로 인한 오버헤드도 함께 존재합니다.
또 참조해야할 부분은 shadred_ptr은 자원을 해제할때에 delete를 사용한다는 점입니다.
delete[] 연산자가 아닙니다.
다시 말하자면 배열에 대해서 shared_ptr을 쓰면 안됩니다. (해제해주지 못합니다.)
std::tr1::shared_ptr<int> spi(new int[1024]);
이런식으로 쓰면 상당히 곤란합니다.
또한 C++라이브러리에는 배열을 위해 준비된 스마트 포인터가 존재하지 않습니다.
배열은 vector나 string으로 대체가 가능하기 때문입니다.
3. 결론
결론은 프로그래머가 직접 하나하나 delete를 해주는 것은 상당히 실수할 확률이 높은 방법이라는 것입니다.
shared_ptr같은 자원관리 클래스를 적극 활용하는 것이 그러한 실수를 피하는 방법입니다.
물론 배열같은것들은 자원관리 클래스를 사용하기 어렵습니다.
이럴때에는 따로 이들을 관리하는 클래스를 만들어서 관리하시길 바랍니다.
이것만은 잊지 말자!
- 자원의 누출을 막기 위해, 생성자 안에서 자원을 획득하고 소멸자에서 그것을 해제하는 RAII객체를 사용합시다.
- 일반적으로 널리 쓰이는 RAII 클래스는 tr1::shared_ptr 그리고 auto_ptr입니다.
이 둘 가운데 tr1::shared_ptr이 복사 시에 동작이 직관적이기 때문에 보통 더 좋습니다.
반면, auto_ptr은 복사되는 객체(원본)를 null로 만들어 버립니다.
(현재 auto_ptr은 삭제되었습니다.)
https://yeoul0714.tistory.com/48
[Effective C++] 항목 14: 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자
1. 개요이번 항목은 자원관리 클래스를 만들때 복사 동작에 대해서 어떻게 처리해야할지를 다루는 문서입니다. 예를 하나 들어보도록 하겠습니다.void lock(Mutex* pm); // pm이 가리키는 mutex에 잠금을
yeoul0714.tistory.com
https://yeoul0714.tistory.com/46
[C++] Smart Pointer
https://www.inflearn.com/course/%EC%96%B8%EB%A6%AC%EC%96%BC-3d-mmorpg-1/dashboard [C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 | Rookiss - 인프런Rookiss | , MMORPG 개발에 필요한 모든 기
yeoul0714.tistory.com
'Effective C++ > Chapter 3: 자원관리' 카테고리의 다른 글
[Effective C++] 항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자 (0) | 2025.05.04 |
---|---|
[Effective C++] 항목 16: new 및 delete를 사용할 때는 형태를 반드시 맞추자 (0) | 2025.05.02 |
[Effective C++] 항목 15: 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자 (0) | 2025.04.29 |
[Effective C++] 항목 14: 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자 (0) | 2025.04.29 |