2015-01-17 3 views
0

리사이클 러 클래스의 객체를 사용하여 객체 만 삭제되는 클래스 (소멸자는 가상 임)를 작성했습니다. 그러나 나는 어느 누구라도 나의 리사이클 러 클래스에 대한 지식이 없어도 그 클래스의 객체를 삭제할 수 있다는 것을 발견했다.액세스를 얻기 위해 C++ 타입 캐스팅

class A 
{ 
public: 
    A() {qDebug() << "cTor: A";} 

protected: 
    virtual ~A() {qDebug() << "dTor: A";} 
}; 

class B 
{ 
public: 
    virtual ~B() {cout << "dTor: B";} 

protected: 
    B() {cout << "cTor: B";} 
}; 

A *a = new A; 
delete (B*)a; // How is this possible !!?? 

출력 :

다음과 같은 예를 고려해보십시오

cTor: A 
dTor: A 

가능한 경우를 나는 A의 소멸자가 아닌 가상의 마지막 서브 클래스를하지 않고이 문제를 방지하기 위해 무엇을 할 수 있는가?

+2

'delete (B *) a; // 이것이 가능한 방법 !! 올바른 캐스트 (예 :'static_cast <>')를 사용해 보면 알 수 있습니다. –

+0

@ πάντα 예 ..하지만 msvC++ 12 및 mingw 4.92에서 모두 작동하는 이유는 무엇입니까? – SaMax

+0

정의되지 않은 동작은 정의되지 않은 동작입니다. 정말 아무것도 작동하지 않습니다. –

답변

2

위에서 언급 한 경우 B의 소멸자의 주소가 포인터의 오프셋과 관련하여 A의 소멸자와 동일하다는 것은 운이 좋았습니다.

가상 소멸자는 개체의 vftable에있는 또 다른 항목입니다. 방금 메모리 주소에 액세스하면 소멸자를 호출 할 수 있습니다.

여기에 이러한 일들이 해결 방법을 보여주는 코드 예제입니다 :

class A 
{ 
public: 
    virtual void foo() {printf("foo !");}; 
}; 
class B 
{ 
public: 
    virtual void bar() {printf("bar !");}; 
}; 
... 
A* a = new A(); 
((B*)a)->bar(); 

은 분명히 내가 B-> 줄을 호출하고 B도 A A가없는하여 foo를 호출 할 수 있습니다 !!!! 매직? 아니. B -> bar는 A -> foo와 같은 주소를 가지고 있습니다. 개발자가 올바른 방법을 알고하지 않는 경우

: 귀하의 예를 고려하여 소멸자는이 라이브러리 개발 POV에서 안전한지 귀하의 코멘트에 대해서는 B.

의 소멸자와 같은 주소를 가지고 캐스트가 문제가 아니거나 개발자가 정말로 라이브러리를 해독하기를 원한다면 그렇게 할 것입니다. 일을 올바르게 사용할 때 작업 코드를 제공하는 것이 당신의 임무입니다. 라이브러리 사용자가 라이브러리에서 캐스트 객체를 재 해석하거나 다른 비표준의 정의되지 않은 동작을 사용하려는 경우에는 아무 것도 만들 수 없습니다 (예를 들어, 임의의 친구가 malloc을 사용하여 객체를 할당하려는 것이 자신의 잘못이 아닙니다 ... 재미있는 거래 처리 그 젠체하는 사람과!).

+0

LOL about malloc. 그것은 C++의 재앙입니다. LocalAlloc 너무 ... –