2017-03-16 5 views
0

다음은 가상 소멸자를 설명하기위한 예제입니다 (http://www.geeksforgeeks.org/g-fact-37/ 참조). 이 예제를 기반으로 코드를 수정하고 메모리 누수에 대해 질문합니다.가상 소멸자없이 기본 클래스 포인터를 삭제할 때 메모리 누수가 발생합니까?

기본 클래스의 변수가 int num이고 파생 클래스가 float money의 변수를 가지고 있다고 가정합니다.

delete base_ptr;을 호출하면 기본 클래스의 소멸자가 가상이므로 ~derived()을 먼저 호출 한 다음 ~Base()을 호출해야합니다.

내 질문은 "삭제 기능을 할 수있다는 모두 INT의 납입 (기본 클래스)에 할당 된 메모리를 해제하고 돈 (파생 클래스)를 떠 것이다 그래야 똑똑?

내가 base_ptr 타입의 포인터라고 생각합니다 Base *이므로 Base 클래스에 필요한 메모리 양을 늘릴 수는 있지만 base_ptr이 Base 클래스의 유형을 가리키는 경우에도 int와 float가 모두 해제 된 것으로 보입니다. 누수가없는 경우 ~Base()을 비가 상 destructor로 만들면 ~Base()이 아닌 가상 소멸자를 사용하면 ~Derived()이라는 호출이 누락됩니다. 기본 클래스와 파생 클래스 둘 다 "동적으로"할당되지 않으므로 ~Derived()은 실제로 무료 전혀 메모리가없고 delete의 기능은 int numfloat money의 메모리를 모두 비 웁니다.

#include <iostream> 
using namespace std; 

class Base { 
public: 
    int num; 

Base(int n):num(n){ 
    cout<<"Base::Constructor\n"; 
} 
    virtual ~Base(){ 
    cout<<"Base::Destructor\n"; 
} 
}; 

class Derived : public Base { 
private: 
    float money; 
public: 
Derived(int n, float m):Base(n),money(m){ 
    cout<<"Derived::Constructor\n"; 
} 
~Derived(){ 
    cout<<"Derived::destructor\n"; 
} 
}; 



int main() { 
    Base *base_ptr = new Derived(1,200.0); 
    delete base_ptr; 
    return 0; 
} 
+0

Base 소멸자가 가상이 아닌 경우이 코드는 정의되지 않은 동작입니다. –

+0

먼저 가상 소멸자가 없으면 코드에 정의되지 않은 동작이 발생하고 보이지 않는 유니콘의 색상에 대해 논쟁의 여지가 없습니다. 둘째, 프로그램이 "메모리의 일부만 비울지"를 묻기 전에'malloc'과'free'를 어떻게 사용하는지 생각해보고 할당 해제 할 메모리의 양을'free'라고 어떻게 생각하는지 물어보십시오 . –

+0

C++ 표준은 기본 클래스 포인터를 통해 파생 클래스 인스턴스를 삭제하면 정의되지 않은 동작임을 명시 적으로 명시합니다. 당신이 "시스템을 속일 수있는"때를 알아내는 것은 가치가있는 것 같지 않습니다. – PaulMcKenzie

답변

2

설명하는 것은 정의되지 않은 동작입니다. 즉, 메모리 누출뿐만 아니라 모든 이상한 요소가 잘못 될 수 있음을 의미합니다. 상속 가상이 아닌 경우

그러나 실제로

가, 파생 클래스가 다른 기본 클래스가없는, 그리고 파생 클래스가 아닌 사소한 소멸자 회원이 없습니다, 당신은 아마 호출 Base::~Base() 소멸자를 가져온 다음 operator delete라는 것이다 포인터에. operator delete(void*) 함수는 포인터를 가져 와서 가리키는 모든 메모리를 비 웁니다. 따라서 "메모리 누수"가 없습니다.

+0

1. '삭제'는 처음에 'new'에 의해 할당 된 메모리를 항상 해제합니다. 나중에 다른 유형으로 캐스팅해도됩니까? 예를 들어, int * ptr = new int (5); delete (char *) ptr; char를 위해서가 아니라 int를 위해 할당 된 메모리를 여전히 자유롭게 할 수 있을까? – jaedong

+0

2. 실행 순서가 (가상 소멸자로) 1) ~ Derived(); varible float 돈을 "undefined"로 만들지 만 float 돈을 위해 할당 된 메모리를 실제로 "자유롭게"하지는 않습니다. 2) ~베이스(); 변수 int num을 "undefined"로 만들고 여전히 메모리를 비우지 않습니다. 3) 삭제는 결국 기본 클래스와 새로 파생 클래스에 의해 할당 된 파생 클래스에 대한 메모리를 모두 비 웁니다. 맞아? 나는 이것이 내가 이해할 필요가있는 미묘한 2 점이라고 생각한다. – jaedong

+0

@ja 님 - 당신은 너무 열심히 노력하고 있습니다. :-) 비슷한 이름에도 불구하고, 언어에 의해 정의 된'delete' 연산자와 라이브러리에 정의 된'operator delete (void *)'는 서로 다른 두 가지입니다. 'delete ptr'에서 포인터는'new'에서 리턴 된 포인터와 올바른 타입을 가져야합니다. 그렇지 않으면 호출 할 소멸자를 어떻게 알 수 있습니까?3 번 부분에서'operator delete (void *)'가 호출 될 때, 메모리는'free'처럼 타입이 지정되지 않고, 런타임은 어쨌든 크기를 마 법적으로 알고 있습니다 (여러 가지 가능한 방법 중 하나로, C++ 표준). –