Утечка памяти после наведения на НОВЫЙ объект

struct StructA {

    StructA(parameters) { ... } //StructA onstructor
};

struct StructB {

    StructA *pObjectA;
    int counter = 0;

    void function() {
        if (counter < 1) { pObjectA = new StructA[100]; }

        pObjectA[counter] = *new StructA(parameters); //Memory leak here
        counter++;
    }
};

struct StructC {

    StructB objectB;

    ~StructC() { //StructC destructor
        delete[] objectB.pObjectA;
        objectB.pObjectA = NULL;
    }
};

int main() {

    StructC objectC;
    for (int i = 0; i < 900; i++) {
        objectC.objectB.function();
    }

    return 0;
} //Struct C destructor here

Мне нужно создать массив объектов и затем, при каждом вызове objectB.function(), передавать конкретные параметры в конструктор StructA. Приведенный выше код работает отлично, за исключением утечки памяти, от которой я не могу избавиться.

Я предполагаю, что деструктор StructC удаляет только массив объектов, а не каждый * новый StructA(параметры). Я попытался немного поиграться с указателями и удалить [], но все, что я получил, это ошибки доступа к памяти. Это единственный способ думать, что это работает. Вся помощь приветствуется.

2 ответа

Деструктор класса должен освобождать ресурсы, которые были получены в его конструкторе. Кажется, вы хотели отложить удаление массива, выделенного в одном классе, деструктору второго класса. Это никогда не хорошая идея. В лучшем случае вам не нужно ничего делать в деструкторе, потому что вы используете автоматическое хранение (означает, что подсказывает название: память управляется автоматически).

Ваш код может выглядеть так:

struct StructA {    
    StructA(parameters) { ... } //StructA onstructor
};

struct StructB {
    std::vector<StructA> pObjectA;
    int counter = 0;

    void function() {
        if (counter < 1) { pObjectA.reserve(100); }
        pObjectA.emplace_back(parameters);    
        counter++;
    }
};

struct StructC {
    StructB objectB;
};

int main() {

    StructC objectC;
    for (int i = 0; i < 900; i++) {
        objectC.objectB.function();
    }    
    return 0;
}

Обратите внимание, что я попытался сохранить структуру, как есть, возможно, есть другие вещи, которые нужно изменить. Например, вам не нужно counter, как вы можете использовать std::vector::size запросить количество элементов в векторе.

PS: Как вы уже заметили, это утечка памяти:

  pObjectA[counter] = *new StructA(parameters); //Memory leak here

Не совсем понятно, почему вы написали этот код в первую очередь. Идоматический способ создания объекта типа StructA является StructA a; (ничего нового!).

Как вы правильно предположили, утечки памяти вызваны неправильной очисткой всех new с соответствием delete, Однако в идиоматическом C++ нет смысла использовать new а также delete непосредственно.

использование std::vector, std::shared_ptr а также std::unique_ptr чтобы RAII отслеживал динамически созданные объекты, ссылки на них и когда нужно их очистить. Мало того, что это более надежно, это также намного короче и легче для чтения.

С общей общей структурой вашего кода:

#include <memory>
#include <vector>

struct StructA {
};

struct StructB {
    std::vector<std::shared_ptr<StructA>> objectAs;

    void function() {
        objectAs.push_back(
            std::make_shared<StructA>( /*parameters*/ )
        );
    }
};

struct StructC {
    StructB objectB;
};

int main() {
    StructC objectC;
    for (int i = 0; i < 900; i++) {
        objectC.objectB.function();
    }
    return 0;
}
Другие вопросы по тегам