2012-04-27 3 views
0

Я вмешивался, тестируя утечки памяти с помощью Intel Inspector, когда заметил что-то, чего не должно быть. Я наследую от std :: vector, который не должен иметь виртуального деструктора, у меня есть дополнительный член в производном классе, я занимаюсь динамическим распределением памяти на нем, в основном создаю производный класс в куче, отбрасываемый в базовый класс , вызывать удаление ... и не обнаруживается утечка памяти ??? По всей логике я должен получить утечку памяти.Почему это не утечка памяти? Или это? Удаление указателя базового класса без виртуальных деструкторов

template <typename T> 
class DynamicArray : public std::vector<T> { 
public:  
    DynamicArray() : children(nullptr) { 
     children = new int(50); 
    } 
    ~DynamicArray() { 
     if (children) delete children; 
    } 
    DynamicArray& operator<<(const T& value) 
    { 
     push_back(value); 
     return *this; 
    } 
private: 
    int *children; 
}; 


int main() { 
    DynamicArray<int> *pArray = new DynamicArray<int>; 
    (*pArray) << 4 << 5; 
    static_cast<std::vector<int>*>(pArray); 
    delete pArray; 
} 
+1

особенно с вопросов, связанных с этим, это хорошая практика, чтобы объявлять деструкторы 'virtual' (хотя для этого важно, чтобы это относилось к базовому классу) – RageD

+4

Унаследовать от контейнеров STL плохо, mmkay? Используйте составные или не-членные функции шаблонов без друга, если вы должны расширить один из них. – AJG85

+0

@ AJG85 - да, да, как алкоголь и табак, неплохие, но это не помешало людям перестать использовать и злоупотреблять ими. Я только планирую использовать свой производный класс очень ответственно, таким образом, обширное тестирование потенциальных проблем. – dtech

ответ

7

pArray еще типа DynamicArray<int> и WIIL называют правильный деструктор, это, скорее всего, утечка:

std::vector<int>* wrong = static_cast<std::vector<int>*>(pArray); 
delete wrong; 

редактировать: как Бен Voigt правильно сказали, это последний фрагмент кода фактически неопределенное поведение, поскольку деструктор std::vector не является виртуальным. Так что даже не гарантирует, что это будет течь

+7

Это неопределенное поведение, потенциально более катастрофическое, чем утечка памяти. –

+0

Вы правы, с новым указателем у меня есть 4-байтовая утечка. Спасибо за разъяснение, я каждый день узнаю что-то новое. – dtech

+0

Ваш предварительный ответ был лучше ... –

5

Это выражение не имеет никаких побочных эффектов:

static_cast<std::vector<int>*>(pArray); 

В коде на delete и new на самом деле идеально соответствуют друг другу.


Кроме того, эта линия выделяет ОДИН int, поэтому вы можете не заметить его в анализе памяти:

children = new int(50); 
+0

yep, одного int достаточно, это просто для целей тестирования – dtech