2011-03-16 2 views
1

소멸자가 실제 작업을 수행하지 않는 것처럼 보이는 다음 코드를 고려하면 valgrind는 소멸자를 사용하지 않고 메모리 누수가 있음을 분명히 보여주었습니다. 어떤 경우라도 소멸자가하는 일은 무엇이든 설명 할 수 있습니까?소멸자는 자동으로 무엇을합니까?

#include <iostream>                  
using namespace std;                 

class A                     
{                      
private:                    
    int value;                   
    A* follower;                  
public:                     
    A(int);                    
    ~A();                   
    void insert(int);                 
};                      

A::A(int n)                    
{                      
    value = n;                   
    follower = NULL;                 
}                      

A::~A()                    
{                     
    if (follower != NULL)               
     delete follower;                
    cout << "do nothing!" << endl;            
}                     

void A::insert(int n)                 
{                      
    if (this->follower == NULL) {              
     A* f = new A(n);                
     this->follower = f;                
    }                     
    else                    
     this->follower->insert(n);              
}                      

int main(int argc, char* argv[])              
{                      
    A* objectA = new A(1);                

    int i;                    
    for (i = 0; i < 10; i++)               
     objectA->insert(i);                

    delete objectA;                  
} 
+0

조용하지만 치명적인. 그것은 추종자를 삭제합니다. – Anycorn

+0

네,하지만 실제로 삭제는 결국 아무 것도하지 않는 소멸자를 호출합니다. – zhanwu

+0

당신의 소멸자가 포인터 "추종자"를 삭제한다고 생각합니다. memmory에 저장된 가치에 대한 언급을 잃었습니다. 그러나 memmory는 할당된다. 따라서 당신은 가치에 접근 할 수 없으며 당신은 당신의 기억 공간을 낭비합니다. – tomasBULL

답변

3

insert() 메서드는 힙에 새 A를 만들고이를 폴 더 포인터로 다음 요소에 연결합니다. 따라서 A에 대한 소멸자가 없으면 팔로어가 가리키는 객체는 절대로 삭제되지 않습니다.

+0

나는 결과를 이해하지만 'follow follower'가 아무 일도하지 않는 소멸자를 호출하기 때문에 이것이 어떻게 달성되는지 이해하지 못한다. – zhanwu

+0

하지만 뭔가를합니다. "아무것도하지 마라!"라는 내용이 인쇄되어 있습니다. 붉은 청어. A의 소멸자가 팔로워를 삭제할 때 삽입 메소드에서 new로 작성된 객체 A와 연관된 메모리를 해제합니다. 그런 다음 해당 객체에 대한 소멸자를 호출합니다 (잘 수행됩니다). 그런 다음 두 번째 A 객체의 팔로워 포인터에서 연결된 목록의 맨 아래까지 delete를 호출합니다. 따라서 main에서 objectA를 삭제하면 연결된 목록의 모든 A 객체가 삭제됩니다. –

+0

내 이해, 소멸자를 정의하면 '삭제'가 사용자 정의 소멸자를 호출합니다. 그렇지 않으면 컴파일러가 대신 사용자 정의 소멸자를 호출합니다. 내 코드에서 소멸자는 자신을 호출하거나 무언가를 출력하는 방식으로 정의됩니다. 나는 기억이 어떻게 풀리는 지, 부분을 보지 못한다. – zhanwu

0

이 코드는 소멸자가 실제 작업을 수행하는 것처럼 보입니다. ~ A()를 호출하는 팔로워 포인터를 삭제하고 팔로워를 삭제합니다.

소멸자를 생략하면 할당 된 노드가 모두 삭제되지 않습니다.

1

먼저 운동 용으로 바란다. 그렇지 않으면 std::forward_list<int>이 훨씬 더 적합합니다 (vector<int> 일 것).

둘째, 소멸자 역할은 단순히 코드를 실행하는 것입니다.이 코드는 follower에 의해 획득 된 리소스를 해제하는 것입니다.

delete follower에 대한 호출은 두 가지 일을 수행합니다

  • 그것이 follower
  • 의 소멸자를 호출 그것을 다음 릴리스followerdelete에 호출하지 않고

를 저장하고있는 메모리 , 당신은 메모리 누수가 있습니다.

주 :

  • 귀하의 클래스는 복사 생성자와 대입 연산자 new-main에서 그것은 필요가 없습니다
  • , A의 인스턴스 없다.
+0

클래스의 의미를 감안할 때, 복사 및 양도 금지. –

+0

@James : 적절히 금지하거나 정의하십시오 (결국'std :: forward_list'는 약간의 비용으로도 복사가 가능합니다). 그러나 확실히 그들에 대해 뭔가를하십시오 :) –