생성자 메모리 누수 예외처리 문제

dragonHu의 이미지

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가 힙 객체일 경우에 어느 시점에 어떤 방법으로 다른 멤버변수들이 해제되는지 궁금합니다.
제가 잘못 알고 있거나 모르는 점에 관해서도 지적해 주시면 감사하겠습니다.
jick의 이미지

name과 addr이라는 변수는 안 보이는데요. theName과 theAddr을 말씀하시는 거라면, BookEntry 멤버 변수이므로 자동으로 메모리가 해제됩니다. 즉 BookEntry의 생성자가 정상적으로 수행되면 나중에 소멸자에서 theName/theAddr의 소멸자를 부르게 되고, 생성자에서 theName/theAddr을 생성한 다음에 exception이 발생하면 그 순간 theName/theAddr의 소멸자가 불리게 됩니다.

그리고 C++11 이상을 쓸 수 있는 환경이라면, 저렇게 try/catch 블럭으로 묶는 것보다 std::unique_ptr을 사용하시면 훨씬 쾌적하게 같은 일을 할 수 있고 실수할 가능성도 대폭 낮아집니다. 한번 찾아보세요.

dragonHu의 이미지

감사합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.