Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Освобождение памяти - в каких случаях

490
16 апреля 2008 года
frid-karatel
357 / / 15.09.2007
В каких случаях надо освобождать память от переменной? Создал проект, но он постепенно загружает оперативу, и не освобождает...

Код:
void Func1()
{
  TButton* btn;
  btn  = Form1->Btn;
  btn->Name = "New Name";
  //Надо как-то осовобождать btn?
}

void Func2(TButton* btn)
{
  btn->Name = "New Name";
  //надо освобождать btn?
}

void Func3()
{
  tagMYSTRUCT ms = new tagMYSTRUCT;
  ms.Name = "New Name";
  /*global*/  GlobalMyStruct = ms;
  //Надо освобождать ms?
}

void Func4()
{
  TButton* btn = (TButton*)Form1->FindComponent("Button1");
  btn->Name = "New Name";
  //Надо освобождать btn?
}

void Func5()
{
  /*global*/ unsigned char* uc = new unsigned char[100];
  //uc объявлено глобально, функция func5 выполняется через, скажем 5 секунд постоянно, вызываясь с главной формы. Надо освобождать uc?
}

void Func6()
{
  /*global*/  unsigned char** uc;
  for (int a = 0; a < 100; a++)
    uc[a] = new unsigned char[200];
  //uc - глобальная переменная. Надо освобождать uc? если освобождать, то только uc, или в цикле от 0 до 100 освободить uc[a]?
}


Вот некоторые примеры кода, в которых я не знаю, что делать - освобождать или нет. Буду признателен за другие примеры, которые я не привел. Этот вопрос встал очень жестко, происходит очень плохая вещь - непомерное расходование памяти. В результате, бывает, что программа просто вылетает из-за недостатка, т.е. винда просто "убивает" мою прогу...
11
16 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: frid-karatel
В каких случаях надо освобождать память от переменной? Создал проект, но он постепенно загружает оперативу, и не освобождает...

Код:
void Func1()
{
  TButton* btn;
  btn  = Form1->Btn;
  btn->Name = "New Name";
  //Надо как-то осовобождать btn?
}

void Func2(TButton* btn)
{
  btn->Name = "New Name";
  //надо освобождать btn?
}

void Func3()
{
  tagMYSTRUCT ms = new tagMYSTRUCT;
  ms.Name = "New Name";
  /*global*/  GlobalMyStruct = ms;
  //Надо освобождать ms?
}

void Func4()
{
  TButton* btn = (TButton*)Form1->FindComponent("Button1");
  btn->Name = "New Name";
  //Надо освобождать btn?
}

void Func5()
{
  /*global*/ unsigned char* uc = new unsigned char[100];
  //uc объявлено глобально, функция func5 выполняется через, скажем 5 секунд постоянно, вызываясь с главной формы. Надо освобождать uc?
}

void Func6()
{
  /*global*/  unsigned char** uc;
  for (int a = 0; a < 100; a++)
    uc[a] = new unsigned char[200];
  //uc - глобальная переменная. Надо освобождать uc? если освобождать, то только uc, или в цикле от 0 до 100 освободить uc[a]?
}


Вот некоторые примеры кода, в которых я не знаю, что делать - освобождать или нет. Буду признателен за другие примеры, которые я не привел. Этот вопрос встал очень жестко, происходит очень плохая вещь - непомерное расходование памяти. В результате, бывает, что программа просто вылетает из-за недостатка, т.е. винда просто "убивает" мою прогу...



где есть new должно быть и delete (если для объекта не предусмотрено иное удаление)

490
16 апреля 2008 года
frid-karatel
357 / / 15.09.2007
Цитата: oxotnik333
где есть new должно быть и delete (если для объекта не предусмотрено иное удаление)


про это я читал немного... а в других случаях ничего не надо освобождать. например через Free(), Release(), ну и т.п.... ?

11
17 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: frid-karatel
про это я читал немного... а в других случаях ничего не надо освобождать. например через Free(), Release(), ну и т.п.... ?



Free() - паскалевский метод в С++ не использовать! (в хелпе к ВСВ написано подробно)
Release() - Метод СОМ объектов (уменьшает счетчик СОМ объекта на единицу)

240
17 апреля 2008 года
aks
2.5K / / 14.07.2006
Цитата: frid-karatel

 
Код:
void Func1()
{
  TButton* btn;
  btn  = Form1->Btn;
  btn->Name = "New Name";
  //Надо как-то осовобождать btn?
}


Тут ты просто проинициализировал btn другим указателем. Очистишь btn, одновременно отчистится и Form1->Btn. А вот если ты под Form1->Btn где то выделял память, то ее да, надо удалять когда она стала ненужна.


Цитата: frid-karatel

 
Код:
void Func2(TButton* btn)
{
  btn->Name = "New Name";
  //надо освобождать btn?
}


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

Цитата: frid-karatel

 
Код:
void Func3()
{
  tagMYSTRUCT ms = new tagMYSTRUCT;
  ms.Name = "New Name";
  /*global*/  GlobalMyStruct = ms;
  //Надо освобождать ms?
}


ну во первых тогда уж надо писать:
tagMYSTRUCT *ms = new tagMYSTRUCT;
Иначе у тебя это просто не соберется.
Ну а удалять уже надо GlobalMyStruct. При этом если GlobalMyStruct уже на что то указывает, ее надо отчстить перед присваиванием ms.

Цитата: frid-karatel

 
Код:
void Func4()
{
  TButton* btn = (TButton*)Form1->FindComponent("Button1");
  btn->Name = "New Name";
  //Надо освобождать btn?
}


Смотри первый пункт. Кстати что будет если FindComponent ничего не найдет? Ты это предусматриваешь?

Цитата: frid-karatel

 
Код:
void Func5()
{
  /*global*/ unsigned char* uc = new unsigned char[100];
  //uc объявлено глобально, функция func5 выполняется через, скажем 5 секунд постоянно, вызываясь с главной формы. Надо освобождать uc?
}


В данном случае uc локальная, а не глобальная. Даже если переменная с таким же именем объявленна глобально (что само по себе уже плохо), то описанная в функции переменная перекрывавет глобальную. ну и соответсвенно глобальной ничего не присваивается и выделенная память теряется при выходи из функции.

Цитата: frid-karatel

 
Код:
void Func6()
{
  /*global*/  unsigned char** uc;
  for (int a = 0; a < 100; a++)
    uc[a] = new unsigned char[200];
  //uc - глобальная переменная. Надо освобождать uc? если освобождать, то только uc, или в цикле от 0 до 100 освободить uc[a]?
}


Аналогично пошлому примеру uc - не глобальная здесь, а локальная. И соответсвенно после завершения функции указатель на выделенную память теряется. И еще прежде чем пытаться индексировать указатель uc, надо сначала под него тоже выделить память (в данном случае 100 элементов типа char *).
А вобще если все было правильно - то да надо в цикле удалять uc[0-100], а потом удалить еще и сам uc.

Вобщем что могу сказать - срочно нужно взять книжку по С или С++ желательно с примерами и почитать про указатели. Налицо явное непонимание, что это такое. Я серьезно, иначе не понятно как ты что то из этого дальше будешь делать.

490
21 апреля 2008 года
frid-karatel
357 / / 15.09.2007
А как тут поступить? Вообще, можно так делать или нельзя?

Код:
unsigned char* CharToChar(unsigned char* Src, unsigned char* Dest, int Length)
{
  unsigned char* r = new unsigned char[Length];
  for (int a = 0; a < Lentgh; a++)
  {
    Dest[a] = Src[a];
    r[a] = Src[a];
  }
  //Делаю еще манипуляции с r[];
  return r;  //получается, что в этой функции не очищается память, т.е. нет delete[] r. А как это сделать, если мне надо вернуть значение?
}

AnsiString CharToStr(unsigned char* Src, int Length)
{
  AnsiString s = "";
  for (int a = 0; a < Length; a++)
  {
    s = s + (char)Src[a];
  }
  return s;
}

void Proc()
{
  for (int a = 0; a < 10000; a++)
  {
    int l;
    unsigned char* uc1 = new unsigned char[l];
    //Делаю что-то с uc1
    unsigned char* uc2 = new unsigned char[l];
    CharToChar(uc1, uc2, l);
    //Делаю что-то с uc2;
    ShowMessage(CharToStr(CharToChar(uc2, uc1, l)));  //Если выполнять такую функцию, то получается, что я не очищаю возвращаемый unsigned char[], т.е. происходит забивание памяти
    delete[] uc1;
    delete[] uc2;
  }
}
11
21 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: frid-karatel
А как тут поступить? Вообще, можно так делать или нельзя?

Код:
unsigned char* CharToChar(unsigned char* Src, unsigned char* Dest, int Length)
{
  unsigned char* r = new unsigned char[Length];
  for (int a = 0; a < Lentgh; a++)
  {
    Dest[a] = Src[a];
    r[a] = Src[a];
  }
  //Делаю еще манипуляции с r[];
  return r;  //получается, что в этой функции не очищается память, т.е. нет delete[] r. А как это сделать, если мне надо вернуть значение?
}

AnsiString CharToStr(unsigned char* Src, int Length)
{
  AnsiString s = "";
  for (int a = 0; a < Length; a++)
  {
    s = s + (char)Src[a];
  }
  return s;
}

void Proc()
{
  for (int a = 0; a < 10000; a++)
  {
    int l;
    unsigned char* uc1 = new unsigned char[l];
    //Делаю что-то с uc1
    unsigned char* uc2 = new unsigned char[l];
    CharToChar(uc1, uc2, l);
    //Делаю что-то с uc2;
    ShowMessage(CharToStr(CharToChar(uc2, uc1, l)));  //Если выполнять такую функцию, то получается, что я не очищаю возвращаемый unsigned char[], т.е. происходит забивание памяти
    delete[] uc1;
    delete[] uc2;
  }
}



1-й случай
2-й случай правильно - AnsiString это контейнер для строки, сам следит за освобождением памяти, как длинна становится ==0
3-й случай тоже правильно (аналогично надо делать и в 1-м случае, передавать возвращаемое через параметр), очищается память уже после вызова всех необходимых ф-й

240
21 апреля 2008 года
aks
2.5K / / 14.07.2006
Ну про первый случай oxotnik333 ссылочку. Подтвержу, что выделять память в функции и потом ее возвращать плохая практика - так как очень легко можно забыть ее отчистить, да и вобще нетривиально это - узнать, что надо принять возвращаемое значение и обязательно его отчистить, что ты сам забываешь кстати сделать в 3-ем примере.
11
21 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: aks
...что ты сам забываешь кстати сделать в 3-ем примере.



он не забыл... в конце стоит delete[] на обе uc1/2

240
21 апреля 2008 года
aks
2.5K / / 14.07.2006
Нет как раз забыл. Есть вызов CharToChar, которая возвращает указатель на выделенную память. О чем я и говорил. Никто его не принимает и он соответственно теряется. Получаем утечку. )
11
21 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: aks
Нет как раз забыл. Есть вызов CharToChar, которая возвращает указатель на выделенную память. О чем я и говорил. Никто его не принимает и он соответственно теряется. Получаем утечку. )



хы, а я думал CharToChar это какая то библиотечная (не самописная) ф-я :) в хелп не лазил за ней
если так, то да, косяк с памятью

490
21 апреля 2008 года
frid-karatel
357 / / 15.09.2007
Получается, что лучше сделать вот-так...?

Код:
void CharToChar(unsigned char* Src, unsigned char* Dest, unsigned char* r, int Length)
{
  for (int a = 0; a < Lentgh; a++)
  {
    Dest[a] = Src[a];
    r[a] = Src[a];
  }
  //Делаю еще манипуляции с r[]; Значение не возвращаю, т.к. оно изменяется автоматически
}

AnsiString CharToStr(unsigned char* Src, int Length)
{
  AnsiString s = "";
  for (int a = 0; a < Length; a++)
  {
    s = s + (char)Src[a];
  }
  //если мне дальше не надо работать с Src в коде функции void Proc(), можно ли сделать тут delete[] Src, и правильно ли это будет? Тогда, переданный массив будет удаляться после использования, и утечки не будет...
  return s;
}

void Proc()
{
  for (int a = 0; a < 10000; a++)
  {
    int l;
    unsigned char* uc1 = new unsigned char[l];
    unsigned char* r = new unsigned char[l];
    //Делаю что-то с uc1
    unsigned char* uc2 = new unsigned char[l];
    CharToChar(uc1, uc2, r, l);
    //Делаю что-то с uc2;
    CharToChar(uc2, uc1, r, l);  //получаю тут r не через return, а через указатель...
    ShowMessage(CharToStr(r));
    delete[] r;
    delete[] uc1;
    delete[] uc2;
  }
}


Но ведь в BCB в справке по функции есть пример кода с использованием strcpy... Там есть возвращаемое значение. Я понял, что возвращается unsigned char* Dest[l], который передается в параметр. В этом случае при delete[] uc2 (т.е. это передаваемый функции параметр Dest) удаляется и то значение, которое было возвращено.

Значит, можно сделать и так...
 
Код:
unsigned char* CharToChar(unsigned char* Src, unsigned char* Dest, int Length)
{
  for (int a = 0; a < Lentgh; a++)
  {
    Dest[a] = Src[a];
  }
  //Делаю еще манипуляции с Dest[];
  return Dest;
}


Тогда с этим кодом будет все ОК и память очиститься... или не очистится, ведь ссылка-то теряется...
Код:
void Proc()
{
  for (int a = 0; a < 10000; a++)
  {
    int l;
    unsigned char* uc1 = new unsigned char[l];
    //Делаю что-то с uc1
    unsigned char* uc2 = new unsigned char[l];
    CharToChar(uc1, uc2, l);
    //Делаю что-то с uc2;
    ShowMessage(CharToStr(CharToChar(uc2, uc1, l)));
    delete[] uc1;
    delete[] uc2;
  }
}


Но здесь я уже не могу оперировать над третьим - unsigned char* r; Но пример верен, да?
11
21 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
в справке по strcpy позвращается указатель на выделенную память до вызова strcpy (сама она не выделяет память), хотя смысла возврящать тот же указатель что и в параметрвх не вижу, лучше возвращать флаг об успешном/не успешном выполнении ф-ции
490
21 апреля 2008 года
frid-karatel
357 / / 15.09.2007
Цитата: oxotnik333
в справке по strcpy позвращается указатель на выделенную память до вызова strcpy (сама она не выделяет память), хотя смысла возврящать тот же указатель что и в параметрвх не вижу, лучше возвращать флаг об успешном/не успешном выполнении ф-ции



возвращать значение есть смысл, когда надо обработать результат в другой функции, как у меня в примере:
ShowMessage(CharToStr(CharToChar(uc2, uc1, l)));

11
21 апреля 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: frid-karatel
возвращать значение есть смысл, когда надо обработать результат в другой функции, как у меня в примере:
ShowMessage(CharToStr(CharToChar(uc2, uc1, l)));



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

490
21 апреля 2008 года
frid-karatel
357 / / 15.09.2007
Цитата: oxotnik333
с таким же успехом можно в параметры вызываемой ф-ции засунуть не ф-ю которая возвращает результат, а сам результат, ничего не изменится и читаемость кода получше будет



то есть сделать так:

 
Код:
CharToChar(uc2, uc1, l);
ShowMessage(CharToStr(uc1));
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог