2015-01-04 9 views
0

이상한 어설 션 오류가 발생하여이 코드의 문제점을 발견 할 수 없습니다.개체를 삭제하는 동안 C++ 어설 션 오류가 발생했습니다.

어설 션 표현식은 _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)입니다.

가독성을 높이기 위해 코드를 약간 단순화했습니다.

class Creator 
{ 
public: 
    virtual ~Creator() 
    { 
     for (MyObject* item : _list) 
     { 
      delete item; <-- assertion error here 
      item = 0; 
     } 
     _list.clear(); 
    } 

    template <class T> 
    T& create() 
    { 
     T * item = new T(); 
     _list.push_back(item); 
     return *item; 
    } 

private: 
    std::list<MyObject*> _list; 
}; 

class A : public MyObject, public Creator 
{ 
}; 

class B : public MyObject, public Creator 
{ 
}; 

int main() 
{ 
    A a; 
    a.create<A>(); 
} <-- call of destructor 

아이디어는 객체 마녀가 다른 개체를 만들고, 그 개체에 대한 포인터를 저장할 수있는, 창조주를 상속한다는 것입니다. 프로그래머는 참조로 작업 할 수 있습니다. 그리고 "수퍼"객체가 파괴되면 모든 "하위"객체도 파괴됩니다.

template <class T> 
class Creator 
{ 
public: 
    virtual ~Creator() 
    { 
     for (T* item : _list) 
     { 
      delete item; 
      item = 0; 
     } 
     _list.clear(); 
    } 

    T& create() 
    { 
     T * item = new T(); 
     _list.push_back(item); 
     return *item; 
    } 

private: 
    std::list<T*> _list; 
}; 

class A : public MyObject, public Creator<A> 
{ 
}; 

class B : public MyObject, public Creator<B> 
{ 
}; 

int main() 
{ 
    A a; 
    a.create(); 
} 

이제 생성 방법은 (이 예에서는 객체 A) 객체의 한 종류를 생성합니다 : I가 변경하는 경우

프로그램은 마법처럼 작동합니다. 하지만 Create 메서드는 MyObject를 상속하는 모든 개체를 만들 수 있어야합니다. 처음에는 코드의 평화처럼.

이 어설 션 오류에 대한 도움을 주시면 감사하겠습니다. 감사.

+0

무엇이'MyObject'입니까? 그것의 소멸자가 가상인가? –

+0

당신은 여기에'MyObject' 클래스를 보여주지 않았습니다. – Ankur

+0

for 루프에서'item = 0;'을 실행할 수 있는지 확신 할 수 없지만 적어도 쓸모는 없습니다. – wimh

답변

1

문제는 당신을 MyObject 클래스는 가상 소멸자 부족이다, 당신은 기본 클래스 MyObject에 대한 포인터를 사용하여 파생 클래스에 대한 포인터에 delete 전화를 시도하고 있습니다. 기본 클래스 소멸자가 가상이 아닌 경우 기본 클래스 포인터를 통해 파생 개체에 delete을 발급하면 정의되지 않은 동작이 발생합니다. 피연산자의 정적 유형이 동적 유형과 다른 경우

5.3.5 삭제 (제 3 항) 제 대안

(개체를 삭제)은, 정지형 기본 클래스이어야한다 피연산자의 동적 유형 이고 정적 유형에는 가상 소멸자가 있어야하며 동작은 정의되지 않음입니다.

소멸자는 기본 클래스 MyClass 가상 이루어지면 다음 2013 Visual Studio에서 제대로 작동 :

#include <list> 
struct MyObject 
{ 
    virtual ~MyObject() {} 
}; 

class Creator 
{ 
public: 
    virtual ~Creator() 
    { 
     for (MyObject* item : _list) 
     { 
      delete item; 
      item = 0; 
     } 
     _list.clear(); 
    } 

    template <class T> 
    T& create() 
    { 
     T * item = new T(); 
     _list.push_back(item); 
     return *item; 
    } 

private: 
    std::list<MyObject*> _list; 
}; 

class A : public MyObject, public Creator 
{ 
}; 

class B : public MyObject, public Creator 
{ 
}; 

int main() 
{ 
    A a; 
    a.create<A>(); 
} 
+0

매우 유익한 답변을 보내 주셔서 감사합니다. – Radon

0

나는 다중 상속 문제라고 생각한다. 다음은 문제를 재현하는 간단한 방법입니다. 이것은 기본 클래스의 가상 소멸자 될 갖는 가장 유래 타입 캐스팅

  • OR
  • 의해 고정 될 수있다. 이 파괴는 상속 계층 구조를 통해 호출을 얻기 위해 가상으로 기본 클래스 소멸자 (들)을 가지고하는 것이 좋습니다 귀하의 경우

는 가상 함수 접근 방식은 최고입니다.

class A 
{ 
}; 

class B 
{ 
}; 

class C : public A, public B 
{ 
}; 

int main() 
{ 
    // Fails with memory heap error 
    B* pB = new C(); 
    delete pB; 
} 

은 다음과 유사한이기 때문에

int main() 
{ 
    B* pB = new C(); 
    // Casting it to the "full" type will fix it 
    C* pC = static_cast<C*>(pB); 
    delete pC; 
} 

두 번째 프로그램이 작동 해결하려면.

int main() 
{ 
    // Pointer to the "full" type works 
    C* pC = new C(); 
    delete pC; 
} 
+0

감사합니다. 답변에 감사드립니다. – Radon

0

문제가 당신을 MyObject 포인터를 통해 개체를 삭제하려고한다는 것입니다 및 MyObject를 소멸자이다 가상이 아닙니다. MyObject의 소멸자를 가상으로 만들면 MyObject에 대한 포인터를 통해 하위 클래스 개체를 삭제할 수 있습니다. 이 문제에 대한 자세한 내용은 this을 참조하십시오.