C ++ выделяет динамическую память в одной функции и очищает другую функцию

0

Я бы хотел, чтобы эксперты рассмотрели следующий процесс распределения динамической памяти и предложили, есть ли утечки памяти. Следующий код не является реальным используемым кодом, но пытается понять концепцию распределения памяти и де-распределения по-разному.

class ObjMapData
{
private:
int* itsMapData;
........
public:
ObjMapData();
~ObjMapData(){if(itsMapData!= NULL) delete[] itsMapData;}
ClearMemory() {if(itsMapData!= NULL) {delete[] itsMapData; itsMapData= NULL}}
.......
void SetMapData(int* ptrData) { itsMapData = ptrData;} // or should I use int*&ptrData??
int* GetMapData() const { return itsMapData;}
}

Теперь я могу сделать следующее без утечек памяти?

bool Function1(ObjMapData& objMyMap)
{
//populate the ptrData with some data values using many different ways
int* ptrData = new int[1000]; // usually a variable from binary file header

......................
objMyMap.SetMapData(ptrData);
//don't want to delete the memory yet
return true;
}

bool Function2(ObjMapData& objMyMap)
{
int* ptrData = objMyMap.GetMapData();
//do some work such as writing updated data into a binary file
}

bool Function3(ObjMapData& objMyMap)
{
//populate the data
bool bStatus = Function1(objMyMap);

int* ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
..........
bStatus = Function2(objMyMap); // write data to a binary file
objMyMap.ClearMemory(); // not real code  in use, but for understanding the concept
bStatus = Function1(objMyMap); // re-allocate memory
ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
objMyMap.SetMapData(ptrData); // Do I need to set again or member pointer get updated automatically?
return true
}
int main()
{
ObjMapData objMyMap;
bool bStatus = Function3(objMyMap);
//default destructor of objMyMap can take care of the allocated memory cleanup
return 0;
}

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

  • 2
    delete nullptr безопасно, кстати, вам не нужны проверки на ноль. Вы нарушили правило трех, хотя. Что произойдет, если я скопирую ваш объект? Двойное удаление.
  • 2
    Я думаю, что ваш вопрос больше подходит для codereview.stackexchange.com
Показать ещё 6 комментариев
Теги:
memory-leaks
memory-management

1 ответ

1

Хотя это может показаться более связанным со стилем, чем ваш вопрос об утечках памяти, я бы обрабатывал данные конфиденциально в классе:

class ObjMapData
{
private:
int* itsMapData;
// consider adding 'datasize' member variable   
........
public:
ObjMapData(){ itsMapData=NULL; }; // initialise member variable(s)!
~ObjMapData(){ delete[] itsMapData;}
ClearMemory() { delete[] itsMapData; itsMapData=NULL; }
.......
void CreateMapData(int size) { ClearMemory(); itsMapData= new int[size]; }
void FillDataFrom( ???? ) { ???? };
int* GetMapData() const { return itsMapData;}
}

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

EDIT Вы спрашиваете:

Мое беспокойство здесь в том, какое из следующего правильно: void SetMapData (int * ptrData) Vs void SetMapData (int * & ptrData)

Оба являются "правильными" в том смысле, что оба разрешают копирование и использование внешнего (для класса) указателя в вашем классе - в отношении "утечек памяти" это зависит от того, какая часть вашего кода вы хотите управлять памятью, которую вы выделены. Ты мог:

  1. Распределять/освобождать дескриптор класса внутри
  2. Выделите память, используйте некоторый класс для управления им, освободите память вне класса
  3. Имейте класс, выделяющий память, а затем освободите его вне класса
  4. Выделите память, и некоторые классы манипулируют и освобождают ее.

Обычно я нахожу, что 1 и 2 имеют больше смысла, чем 3 или 4. т.е. Легче следить за тем, что происходит, с меньшей вероятностью скрывать ошибки и т.д.

Однако, что касается "утечки памяти": не имеет значения, где указатель на выделенный блок памяти, как он был скопирован, назначен или привязан - это значение как важный адрес памяти. Таким образом, до тех пор, пока вы new и delete этот адрес памяти, вы не будете просачивать память (независимо от того, находятся ли эти действия внутри класса или нет).

Если в вашем приложении вам нужно выделить/деактивировать массив int, внешний для вашего класса, имеет смысл, что функции-члены ссылаются на указатель как подсказку к читателю о том, что класс не несет ответственности за его освобождение, - но некоторые достойные комментарии должны сделать так ясно :)

За прошедшие годы я столкнулся с множеством ошибок из-за неправильного обращения с "передачей владения" выделенной памяти (более того, с хорошим ol 'C), где был написан какой-то фрагмент кода, предполагающий, что он должен освободить блок или кто-то другой сделает это.

Это ответ на ваш вопрос или я пропустил это?

  • 0
    Меня беспокоит то, что из следующего верно: void SetMapData (int * ptrData) против void SetMapData (int * & ptrData), чтобы в основном позволить мне выделять память и, следовательно, заполнять данные в разных функциях, не являющихся членами, и автоматически выделять из них одну функция-член деструктора. Реальный код - это 20000+ строк ... и поэтому пытаюсь выразить свою озабоченность простым примером. Спасибо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню