Удаление массива объектов, преобразованных в базовые указатели

начал перемещать некоторые библиотеки из msvc в mingw и обнаружил очень интересное поведение msvc, когда нужно удалить массив отгороженных объектов. А именно, msvc делает некоторую темную магию (кажется, что любит это делать), и приведенный ниже код выполняется просто отлично, однако в mingw (4.7.2 (вылетает. Я считаю, что mingw работает правильно, а его voodoo msvc — вот проблема для создания спящий жук

Код:

#include <iostream>

class foo{
static int idgen;
protected:
int id;
public:
foo(){
id = idgen++;
std::cout << "Hello  ( foo - "<<id<<")"<<std::endl;
}
virtual ~foo(){
std::cout << "Bye bye ( foo - "<<id<<")"<<std::endl;
};
};

int foo::idgen = 0;class bar: public foo{
double some_data[20];
public:
bar(){

std::cout << "Hello  ( bar - "<<id<<")"<<std::endl;
}
~bar(){
std::cout << "Bye bye ( bar - "<<id<<")"<<std::endl;
}
};

int main()
{
const unsigned int size = 2;
foo** arr = new foo*[size];
{
bar* tmp = new bar[size];
for(int i=0; i<size; i++)
{
arr[i] = &(tmp[i]); //take address of each object
}
}

delete [] arr[0]; //take address of first object, pointer is same as tmp. This also crashes mingw
delete [] arr;

}

Выход из MSVC 2010

Hello  ( foo - 0)
Hello  ( bar - 0)
Hello  ( foo - 1)
Hello  ( bar - 1)
Bye bye ( bar - 1)
Bye bye ( foo - 1)
Bye bye ( bar - 0)
Bye bye ( foo - 0)

И Mingw (разбился при разрушении)

Hello  ( foo - 0)
Hello  ( bar - 0)
Hello  ( foo - 1)
Hello  ( bar - 1)

Мой вопрос в том, как правильно исправить это. Текущий хакфикс, который я придумал, включал в себя только попытку понизить значение до каждого возможного класса и вызвать операцию удаления для указателя с понижением:

if(dynamic_cast<bar*>(arr[0]) != 0)
delete [] dynamic_cast<bar*>(arr[0]);

Есть ли лучший подход, кроме редизайна библиотеки (она не моя)?

4

Решение

В стандартных спецификациях, раздел 5.3.5, параграф 3, относительно delete оператор:

[…] Во втором варианте (удалить массив) если динамический тип удаляемого объекта отличается от его статического типа, поведение не определено.

Так что, действительно, вы не должны полагаться на мягкое поведение Visual C ++ в этом случае и пытаться предоставить массив delete оператор указатель правильного типа, что в основном означает динамическое приведение в вашей ситуации.

Вы можете избежать этой проблемы, используя экземпляр вектора для хранения ваших объектов, выделенных по очереди.

4

Другие решения

gcc 4.7.2 терпит неудачу даже с простым примером здесь -> ideone.com/z876QX#view_edit_box Таким образом, мы не можем использовать виртуальные деструкторы, если это массив.

const unsigned int size = 2;
foo* test = new bar[size];
delete[] test;

Тем не менее, вы уйдете, если вы используете массив указателей, которые позволят вам использовать delete вместо delete[],

http://ideone.com/NfbF3n#view_edit_box

const int size = 5;
foo *test[size];
for(int i = 0; i < size; ++i)
test[i] = new bar;
for(int i = 0; i < size; ++i)
delete test[i];
1

По вопросам рекламы [email protected]