Освобождение памяти - в каких случаях
{
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]?
}
Вот некоторые примеры кода, в которых я не знаю, что делать - освобождать или нет. Буду признателен за другие примеры, которые я не привел. Этот вопрос встал очень жестко, происходит очень плохая вещь - непомерное расходование памяти. В результате, бывает, что программа просто вылетает из-за недостатка, т.е. винда просто "убивает" мою прогу...
{
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 (если для объекта не предусмотрено иное удаление)
про это я читал немного... а в других случаях ничего не надо освобождать. например через Free(), Release(), ну и т.п.... ?
Free() - паскалевский метод в С++ не использовать! (в хелпе к ВСВ написано подробно)
Release() - Метод СОМ объектов (уменьшает счетчик СОМ объекта на единицу)
{
TButton* btn;
btn = Form1->Btn;
btn->Name = "New Name";
//Надо как-то осовобождать btn?
}
Тут ты просто проинициализировал btn другим указателем. Очистишь btn, одновременно отчистится и Form1->Btn. А вот если ты под Form1->Btn где то выделял память, то ее да, надо удалять когда она стала ненужна.
{
btn->Name = "New Name";
//надо освобождать btn?
}
Аналогично. здесь ты передаешь btn параметром. Если тебе он болше не нужен даже в том месте, где ты вызвал функцию - тогда да. Если нужен, тогда удаляй там.
{
tagMYSTRUCT ms = new tagMYSTRUCT;
ms.Name = "New Name";
/*global*/ GlobalMyStruct = ms;
//Надо освобождать ms?
}
ну во первых тогда уж надо писать:
tagMYSTRUCT *ms = new tagMYSTRUCT;
Иначе у тебя это просто не соберется.
Ну а удалять уже надо GlobalMyStruct. При этом если GlobalMyStruct уже на что то указывает, ее надо отчстить перед присваиванием ms.
{
TButton* btn = (TButton*)Form1->FindComponent("Button1");
btn->Name = "New Name";
//Надо освобождать btn?
}
Смотри первый пункт. Кстати что будет если FindComponent ничего не найдет? Ты это предусматриваешь?
{
/*global*/ unsigned char* uc = new unsigned char[100];
//uc объявлено глобально, функция func5 выполняется через, скажем 5 секунд постоянно, вызываясь с главной формы. Надо освобождать uc?
}
В данном случае uc локальная, а не глобальная. Даже если переменная с таким же именем объявленна глобально (что само по себе уже плохо), то описанная в функции переменная перекрывавет глобальную. ну и соответсвенно глобальной ничего не присваивается и выделенная память теряется при выходи из функции.
{
/*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.
Вобщем что могу сказать - срочно нужно взять книжку по С или С++ желательно с примерами и почитать про указатели. Налицо явное непонимание, что это такое. Я серьезно, иначе не понятно как ты что то из этого дальше будешь делать.
{
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;
}
}
{
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-м случае, передавать возвращаемое через параметр), очищается память уже после вызова всех необходимых ф-й
он не забыл... в конце стоит delete[] на обе uc1/2
хы, а я думал CharToChar это какая то библиотечная (не самописная) ф-я :) в хелп не лазил за ней
если так, то да, косяк с памятью
{
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) удаляется и то значение, которое было возвращено.
Значит, можно сделать и так...
{
for (int a = 0; a < Lentgh; a++)
{
Dest[a] = Src[a];
}
//Делаю еще манипуляции с Dest[];
return Dest;
}
Тогда с этим кодом будет все ОК и память очиститься... или не очистится, ведь ссылка-то теряется...
{
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; Но пример верен, да?
возвращать значение есть смысл, когда надо обработать результат в другой функции, как у меня в примере:
ShowMessage(CharToStr(CharToChar(uc2, uc1, l)));
ShowMessage(CharToStr(CharToChar(uc2, uc1, l)));
с таким же успехом можно в параметры вызываемой ф-ции засунуть не ф-ю которая возвращает результат, а сам результат, ничего не изменится и читаемость кода получше будет
то есть сделать так:
ShowMessage(CharToStr(uc1));