2011-01-28 5 views
1

다음은 내 프로그램의 새/삭제 연산자의 패턴입니다. Valgrind는 기억이 "확실히 없어졌다"고 말합니다. 누수가 어디 있는지 나는 꽤 알 수 없었다. 새로운/delete 연산자의 사용법에 문제가 있습니까?valgrind가 메모리 누수를 감지 할 수 없습니다.

class Generic 
{ 
     GenericInterface *gInterface; //GenericInterface is abstract class 

     public: 
      Generic() 
      { 
       gInterface = NULL; 
      } 
      ~Generic() 
      { 
       delete gInterface; 
      } 
      void Create() 
      { 
      gInterface = new Specific(); 
      } 
    }; 

    class Specific : public GenericInterface 
    { 
     MyClass* _myClass; 

    public: 
     Specific() 
     { 
     _myClass = new MyClass; 
     } 

     ~Specific() 
     { 
     delete _myClass; 
     } 

    }; 

    int main() 
    { 
     Generic g; 
     g.Create(); 
    } 

valgrind는 메모리가 손실되었다고 말합니다.

==2639== 8 bytes in 1 blocks are definitely lost in loss record 2 of 45 
==2639== at 0x4026351: operator new(unsigned int) (vg_replace_malloc.c:255) 
==2639== by 0x804D77C: Specific::Specific() (Specific.cc:13) 
==2639== by 0x804DAFC: Generic::Create() (Generic.cc:58) 

답변

11

귀하는 rule of three을 따르지 않습니다. 클래스가 정리해야하는 리소스를 관리하는 경우 은 소멸자, 복사 생성자 및 복사 할당 연산자를 선언해야합니다. 어떤 클래스에도 복사 생성자 또는 복사 할당 연산자가 없습니다.

정말로, C++ 0x의 unique_ptr과 같은 스마트 포인터를 사용해야합니다. Boost의 shared_ptr, C++ TR1 및 C++ 0x; Boost의 scoped_ptr

이 특정 문제를 일으키는 가능성이 문제

잘못된 소멸자가 호출되고 있도록, 기본 클래스를 GenericInterface 소멸자 virtual을 잊어 버린 당신이 동적으로 Specific에서 만든 MyClass 객체가 파괴되지 않습니다 것입니다.

delete 기본 클래스 소멸자가 선언되지 않은 경우 (즉, 메모리 누수에서 충돌까지 나쁜 일이 발생 함을 의미) 기본 클래스 중 하나에 대한 포인터를 통해 객체를 지정하면 정의되지 않은 동작이 발생합니다.

+0

'Virtual ~ GenericInterface() = 0;'을 넣을 때,'~ GenericInterface()'에 대한 Undefined 참조를 얻습니다. 'Specific' 소멸자. – Meebo

+0

@Meebo : 파생 클래스 소멸자가 호출해야하기 때문에 순수하지 않아야합니다. 이를 정의해야합니다 ('GenericInterface :: ~ GenericInterface() {}'). –

2

GenericInterface 소멸자는 아마도 가상이 아니므로 gInterface이 소멸 될 때 GenericInterface 소멸자 만 호출됩니다.

0

GenericInterface 클래스가 가상 소멸자를 선언합니까? 그렇지 않으면 특정 클래스의 소멸자가 호출되지 않으므로 "delete _myClass"행이 실행되지 않습니다. 당신의 인생이 더 재미있는 ++

그냥 다른 방법으로 C :)

0

당신의 일반 클래스 소멸자에서 당신은 또한 그것을 삭제하기 전에 gInterface 포인터를 확인해야합니다. 개체가 파괴되기 전에 Create()가 호출되지 않으면 문제가 발생합니다. 만약 당신의 C++ 컴파일러가 새로운 실패를 던지지 않는다면 다른 클래스도 똑같은 일을 할 것입니다.

관련 문제