생성자 메모리 누수 예외처리 문제
글쓴이: dragonHu / 작성시간: 수, 2017/02/15 - 12:23오전
More Effective C++ 의 항목 10 '생성자에서는 리소스 누수가일어나지 않게 하자' 라는 부분을
공부하다가 든 의문입니다.
class BookEntry { public: BookEntry(const string& name, const string& addr = "", const string& imageFileName = "", const string& audioClipFileName = ""); ~BookEntry(); private: string theName; string theAddr; Image * theImage; AudioClip * theAudioClip; };
다음과 같은 클래스가 있을 때 생성자에서 theAudioClip 에 메모리를 할당할 때 예외가 발생하여
BookEntry 객체의 소멸자를 호출할 수 없어 theImage가 유실되는것을 방지하기 위해 책에서 제시한 해결책 중 하나가 아래의 코드인데요
BookEntry::BookEntry(const string& name, const string& addr, const string& imageFileName, const string& audioClipFileName) : theName(name), theAddr(addr), theImage(imageFileName), theAudioClip(audioClipFileName) { try { if (imageFileName != ""){ theImage = new Image(imageFileName); } if (audioClipFileName != "") { theAudioClip = new AudioClip(audioClipFileName); } } catch (...) { delete theImage; delete theAudioClip; throw; } }
이때 bookEntry 객체가
void testBookEntryClass() { BookEntry b("name", "addr"); }
이렇게 지역변수라면 예외처리에 의해서 리소스 누수가 없고 함수가 끝나면서 스택에있는 지역변수 b도 사라져 b의 멤버인
name과 addr도 없어진다고 이해했지만
void testBookEntryClass() { BookEntry * pb = 0; try { pb = new BookEntry("name", "addr"); } catch (...) { delete pb; throw; } delete pb; }
위와 같이 bookEntry객체가 힙 객체일때는 완전한 생성이 되지않았으니 pb는 null임으로 (책에 new 연산이 성공적으로 끝나기 전에는 pb에 포인터 대입이 이루어 지지 않는다고 적혀있습니다.) delete 를 해도 힙에있는 메모리는 해제되지 않으니 예외처리에 의해 theImage는 누수되지 않는다 해도 name과 addr이라는 멤버가 누수가 일어나는 경우 아닌가요?
책에서는 이게 메모리 누수가 없는 코드라고 해서요
bookEntry가 힙 객체일 경우에 어느 시점에 어떤 방법으로 다른 멤버변수들이 해제되는지 궁금합니다.
제가 잘못 알고 있거나 모르는 점에 관해서도 지적해 주시면 감사하겠습니다.
Forums:
...
name과 addr이라는 변수는 안 보이는데요. theName과 theAddr을 말씀하시는 거라면, BookEntry 멤버 변수이므로 자동으로 메모리가 해제됩니다. 즉 BookEntry의 생성자가 정상적으로 수행되면 나중에 소멸자에서 theName/theAddr의 소멸자를 부르게 되고, 생성자에서 theName/theAddr을 생성한 다음에 exception이 발생하면 그 순간 theName/theAddr의 소멸자가 불리게 됩니다.
그리고 C++11 이상을 쓸 수 있는 환경이라면, 저렇게 try/catch 블럭으로 묶는 것보다 std::unique_ptr을 사용하시면 훨씬 쾌적하게 같은 일을 할 수 있고 실수할 가능성도 대폭 낮아집니다. 한번 찾아보세요.
감사합니다.
감사합니다.
댓글 달기