2011-10-10 4 views
5

다음 예제에서는 생성자가 실행되는 동안 예외가 처리되는 개체에 대해 소멸자가 실행되지 않으므로 메모리 누수가 발생할 수 있습니다. 이 메모리 누수는 어디서 처리합니까?생성자에서 예외 캐치

#include <exception> 

class MyClass { 

public: 
     MyClass() 
     { 
      c = new char[5]; 
      throw std::runtime_error("test"); 
     } 

     ~MyClass() 
     { 
      delete[] c; 
     } 

private: 
    char *c; 
}; 

int main() 
{ 
    try 
    { 
     MyClass Obj; 

    } 
    catch (std::runtime_error) 
    { 

    } 
} 

답변

5

당신은 RAII를 사용하는 것이 더 낫다,이 경우 스마트 포인터를 특정 할 수있다.

또는 Two Phased Construction 전략을 사용할 수 있습니다.

try-catch 블록을 생성자 본문에 항상 사용할 수 있으며 동적으로 할당 한 모든 리소스에 대해 delete를 명시 적으로 호출 할 수 있지만 n 개의 리소스가 동적으로 할당되는 시나리오를 생각하면 명시 적으로 추적 할 때 지저분 해집니다. 이러한 시나리오에서 에서 할당을 해제해야하는 각 리소스에 대해 RAII은 각 리소스가 암시 적으로 자체 할당 해제를 처리하고 각 리소스를 추적하는 오버 헤드를 가질 필요가 없기 때문에 최상의 솔루션을 제공합니다.

boost::scoped_ptr 또는 std::tr1::scoped_ptr은 원시 포인터 대신이 시나리오에 적합합니다.

+2

이 downvote는 무엇을 요구합니까? RAII가이 문제를 해결하는 가장 좋은 방법입니다. 누군가가 달리 말하면 잘못된 것입니다. Downvote에 책임이 있다고 느끼면, 왜 우리에게 설명 할 책임이 있다고 느낍니까? 그리고 만약 당신이 * 단지 * 이것이 잘못되었다고 느끼지 못한다면, 당신은 하향 투표하기에 충분한 자격이되지 않습니다. –

+0

은 C++ 11 관련 항목을 기반으로 한이 솔루션입니까? – user103214

+0

아니요 C++ 03입니다. –

6

생성자에서 예외를 잡아서 깔끔하게 정리하고 (메모리 할당 해제) 메모리 누수없이 예외를 throw합니다. 말했다 throw;

, 예외 및 메모리의 수동 처리에 예외가 함께 잘 가지 않는다 다음 다시 throw

+0

생성자에서 메모리 누수없이 예외를 다시 throw 할 때 소멸자가 호출되지 않았습니다. 이것에 대한 이유가 있습니까? – user103214

+1

@ user974191 : 생성자의 끝 중괄호가 될 때까지 개체 작성이 완료되지 않았습니다. 소멸자는 완성 된 Object에 대해서만 호출됩니다. 생성자가 완전히 실행되지 않으면 객체가 존재하지 않으므로 소멸자가 호출되지 않습니다. –

1

당신은, 당신이 필요로 정리 할 생성자 본문에 예외를 잡을 수 있습니다. c 멤버의 메모리를 자동으로 관리하는 객체 (예 : std::string, std::vector<char>, std::unique_ptr<char[]> 등)를 사용하면 훨씬 편리합니다. 메모리를 관리하는 위 목적 중 하나와 같은 클래스를 작성하는 경우에는 실제로 메모리를 명시 적으로 관리해야합니다.

4

한 가지 방법은 throw의 경우 조건부 예외로 생성자를 시작한 다음 메모리를 할당하는 것입니다.

MyClass() 
    { 
    if(<condition>) 
     throw std::runtime_error("test"); 
    c = new char[<SIZE>]; 
    } 

다른 방법은 생성자 둘러싸는 특별 try-catch() 구문을 사용하는 것입니다

MyClass() 
    try { 
    c = new char[5]; 
    throw std::runtime_error("test");; 
    } 
    catch(std::runtime_error e) { 
    delete[] c; 
    } 

Demo.