Утечка памяти деструктора C ++

Относительно простой вопрос о правильной обработке деструкторов ...

Сначала у меня есть класс, который выглядит примерно так:

class Foo {
public:
    ReleaseObjects() {
        for (std::map<size_t, Object*>::iterator iter = objects.begin(); iter != objects.end(); iter++) {
            delete (*iter).second;
        }
        objects.clear();
    }

private:
    std::map<size_t,Object*> objects;
}

Таким образом, функция просто удаляет объекты, которые были созданы с помощью 'new'. Проблема в классе объекта:

class Bar : public Object {
public:
    Bar() {
        baz = new Baz();
    }

    ~Bar() { delete baz; }
private:
    Baz* baz;
}

Если я добавлю объект типа Baz в Foo, а затем попытаюсь выполнить ReleaseObjects (), я получу утечку памяти (valgrind). Проблема указывает на утечку baz, и я предполагаю, что это означает, что деструктор в bar никогда не вызывается? Итак, я хотел бы знать, как вызвать деструктор Bar при попытке уничтожить этот объект (я не могу изменить класс Bar, но могу изменить Foo).

Изменить: К сожалению, извините за синтаксические ошибки. В любом случае, спасибо за все ответы, глупый, я забыл реализовать правильный деструктор в моем классе Baz! О, и Baz на самом деле является классом шаблона, но я решил, что Baz не имеет отношения к моему вопросу, и что проблема заключается в том, что деструктор в Bar не вызывается ... ну, я ошибался, проблема в конце концов в Baz. Но еще раз спасибо, я думаю, я понял это отсюда!


person Fault    schedule 18.10.2011    source источник
comment
Деструктор в объекте виртуальный? Также опубликуйте класс Object   -  person Tom    schedule 18.10.2011
comment
Этот код не просочился. Этот код даже не компилировался. Пожалуйста, разместите актуальный код.   -  person Benjamin Lindley    schedule 18.10.2011
comment
Можете ли вы опубликовать класс (или что-то еще) для Baz?   -  person MGZero    schedule 18.10.2011
comment
Пожалуйста, опубликуйте минимальную полную программу, демонстрирующую ошибку. Дополнительную информацию см. На sscce.org.   -  person Robᵩ    schedule 18.10.2011
comment
Какую конкретную ошибку вы получаете? И вы добавляете Baz в Foo или Bar в карту Foo? Delete (* iter) .second должен правильно запускать деструктор Bar.   -  person Joe    schedule 18.10.2011
comment
Кроме того, опубликуйте что-нибудь без ошибок. просматривая его, я вижу несколько ошибок, например, пропущенную точку с запятой после удаления baz.   -  person MGZero    schedule 18.10.2011
comment
Вызов delete для объекта Bar в Foo вызывает деструктор Bar. Кроме того, определен ли деструктор Baz? Возможно, Баз не очищает себя должным образом.   -  person    schedule 18.10.2011
comment
Используйте RAII!   -  person sbi    schedule 18.10.2011


Ответы (3)


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

class Object {
 . . .
 virtual ~Object()
 . . .
};
person zdan    schedule 18.10.2011
comment
Это почти то, что я забыл реализовать! И я думал, что моя проблема в другом ... спасибо! - person Fault; 18.10.2011

Я не совсем понимаю ваш сценарий, но поскольку вы " Если у вас публичное наследование, возможно, вам понадобятся виртуальные деструкторы. В частности, базовому классу (Object) нужен виртуальный деструктор.

Обратите внимание, что данный код не может компилироваться. Оператор new возвращает указатель, поэтому baz должен быть указателем.

person Oscar Korz    schedule 18.10.2011

Вы всегда должны использовать умные указатели. Эти типы ведут себя как указатели, но автоматически освобождают память и устраняют необходимость в любых таких функциях. Они избегают всевозможных неприятных ошибок - возможно, включая эту, если вы использовали shared_ptr<Bar> и сбросили его.

Если вы хотите писать нетривиальное программное обеспечение на C ++, вы должны знать и понимать интеллектуальные указатели.

person Puppy    schedule 18.10.2011
comment
Если проблема не в виртуальном деструкторе, я не думаю, что shared_ptr сработает. (Хотя не уверен на 100%) - person Mooing Duck; 18.10.2011
comment
@MooingDuck: он использует стирание типа для деструктора, и поэтому избежит этой проблемы, если вы начали с Bar. - person Puppy; 18.10.2011