2015-01-17 4 views
0

Я писал класс (destructor является виртуальным), объекты которого будут удаляться только с использованием объекта класса recycler. Но я обнаружил, что любой может удалить объект этого класса, не зная моего класса recycler.C++ type casting для получения доступа

Пожалуйста, рассмотрим следующий пример:

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 «s невиртуальном?

+2

'delete (B *) a; // Как это возможно! ?? Это не так. Попробуйте использовать правильный листинг (например, 'static_cast <>'), и вы увидите. –

+0

@ πάντα Да .. Но почему он работает с msvC++ 12 и mingw 4.92? – SaMax

+0

Неопределенное поведение - неопределенное поведение. Ничего действительно _works_. –

ответ

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(); 

Видимо, я могу назвать A Foo по телефону B-> бара и B даже не имеет А !!!! Магия? нет. Случилось так, что B-> bar имеет тот же адрес, что и A-> foo. Учитывая ваш пример, деструктор А имеет тот же адрес, что и деструктор B.

Что касается вашего комментария, если это безопасно от PoV ​​развития библиотеки:

Если разработчик не знает правильный путь к бросить это не ваша проблема, или если разработчик действительно хочет сломать вашу библиотеку, он это сделает. Ваша задача - предоставить рабочий код, когда все будет правильно использовано. Вы не можете ничего сделать, если пользователи библиотеки хотят переинтерпретировать объекты-листы из вашей библиотеки или использовать другие нестандартные неопределенные поведения (это не ваша вина, что какой-то случайный чувак хочет выделять объекты, используя malloc, например ... получайте удовольствие от общения с этим чуваком!).

+0

LOL о malloc. Это катастрофа на земле C++. LocalAlloc тоже ... –