Удаление двойного указателя c++ valgrind для предотвращения утечки памяти

После прочтения: С++ Массив указателей: удалить или удалить []? (ответ Шай Вашид) и http://www.cplusplus.com/forum/beginner/6651/

Я реализовал следующее:

Ядро.h

unsigned int **ConfigMeM;
//.....
~Kernel(){ //destructor
    for (unsigned int i=0; i<MeMSize; i++)
        delete [] MeM[i]; //Valgrind:- Invalid read of size 4
                                       - Invalid free() / delete / delete[] / realloc()
    delete [] MeM; //Valgrind: Invalid free() / delete / delete[] / realloc()

    for (unsigned int i=0; i<_item_tot; i++)
        delete [] ConfigMeM[i]; //Valgrind: Same comments as above
    delete [] ConfigMeM; //Valgrind: same as above
};

Ядро.cpp

//.......
MeM = new unsigned int*[MeMSize];
for (unsigned int i=0; i<MeMSize; i++){
    MeM[i] = new unsigned int[11]; //Valgrind: 14,608 bytes in 332 blocks are definitely lost in loss record 2,021 of 2,036
}
for (unsigned int i=0; i<MeMSize; i++){
    for (int j=0; j<10; j++){
        MeM[i][j] = 0;
    }
}
 //.....
 ConfigMeM = new unsigned int*[_item_tot];
for (unsigned int i=0; i<_item_tot; i++){
    ConfigMeM[i] = new unsigned int[3]; //Valgrind: 1,200 bytes in 100 blocks are definitely lost in loss record 1,131 of 2,036 
}
for (unsigned int i=0; i<_item_tot; i++){
    for (int j=0; j<3; j++){
        ConfigMeM[i][j] = 0;
    }
}
  //.....

Я не уверен, что я делаю неправильно.

Любые предложения, пожалуйста?

Спасибо.


person algoProg    schedule 27.11.2012    source источник
comment
Вы запускаете код в Kernel.cpp несколько раз?   -  person Kerrek SB    schedule 27.11.2012
comment
Является ли код из Kernel.cpp частью конструктора или чем-то еще? Вы объявляете свой собственный конструктор копирования и оператор присваивания копии (в соответствии с правилом трех)? Я предполагаю, что это не так, и в итоге вы получаете два объекта, пытающихся удалить одну и ту же память.   -  person Mike Seymour    schedule 27.11.2012
comment
@KerrekSB Да, ты прав! В верхнем модуле создается несколько копий ядра. Например, в текущем примере это 64. Какое это имеет значение здесь?!   -  person algoProg    schedule 27.11.2012
comment
Какое это имеет значение? Подумайте об этом: int * p = new int; p = new int; p = new int; delete p;   -  person Kerrek SB    schedule 27.11.2012
comment
@KerrekSB Я не хотел бросать тебе вызов!! Я просто хочу спросить, что я могу сделать и как мне изменить свой код?   -  person algoProg    schedule 27.11.2012
comment
Я не чувствовал себя озадаченным :-) Я просто привел простой пример, демонстрирующий проблему, а также предлагающий решение: удалить существующий объект перед выделением нового!   -  person Kerrek SB    schedule 27.11.2012


Ответы (1)


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

Самое простое решение — предотвратить копирование, удалив эти функции:

Kernel(Kernel const&) = delete;
void operator=(Kernel const &) = delete;

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

Если вам нужно скопировать эти объекты, вам нужно будет их реализовать, возможно, для выполнения «глубокой копии», которая выделяет новые блоки памяти.

В качестве альтернативы может быть проще использовать std::vector для управления вашими динамическими массивами; это уже имеет правильную семантику копирования и может быть инициализировано довольно просто:

std::vector<std::vector<unsigned int>> MeM, ConfigMem;

(MemSize, std::vector<unsigned int>(11));
person Mike Seymour    schedule 27.11.2012