Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/29: Рейтинг темы: голосов - 29, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 29.07.2017
Сообщений: 1
1

Очистка памяти в процедуре

29.07.2017, 16:19. Показов 5762. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет!
Скажите, надо ли очищать память в данном примере?

Delphi
1
2
3
4
5
procedure ttt(tss:tstringlist);
begin
  ....
  tss.free;
end;
Вопрос конечно глупый, но так и не понял, надо ли очищать память в таком примере?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.07.2017, 16:19
Ответы с готовыми решениями:

Очистка памяти
Здравствуйте! Скажите пожалуйста, как очищать память после вычислений,если программа не закрыта, но...

MSXML и очистка памяти
Добрый день. Есть поток в котором используется IXMLDOMDocument(CoDomDocument60.create) Создается...

Очистка памяти в программе
Здравствуйте. Есть программа, которая заменяет определенные слова в текстовом файле. Она рабочая,...

Очистка памяти от AnsiString
Есть динамический массив строк Trace: array of AnsiString; По ходу исполнения процедуры массив...

15
Почетный модератор
64304 / 47599 / 32743
Регистрация: 18.05.2008
Сообщений: 115,181
29.07.2017, 16:50 2
Если в этой процедуре завершается работа с tss, то надо.
0
Модератор
9608 / 6216 / 2422
Регистрация: 21.01.2014
Сообщений: 26,510
Записей в блоге: 3
29.07.2017, 16:50 3
Обычно удаляют там же, где и создают... Т.е. в Вашем случае: вы создали СтрингЛист, заполнили его данными и передали в процедуру. Вот после выхода из процедуры и удалите его.
0
225 / 80 / 35
Регистрация: 01.04.2017
Сообщений: 182
29.07.2017, 17:53 4
Обьекты в Delphi передаются только по указателю (мурзилка, последний абзац). Даже если описать их как const их по прежнему можно редактировать (странно конечно, но факт - компялятор даже предупреждение не выдаст).
А значит и уничтожить обьект вы можете в любом месте программы.
Но как уже заметил D1973, - где создали, там и удаляем. Потому как правила хорошего тона есть вероятность того, что по мере роста программы однажды процедура не будет вызвана, а значит и обьект не будет уничтожен.
0
Житель Земли
3003 / 3008 / 391
Регистрация: 26.07.2011
Сообщений: 11,464
Записей в блоге: 1
29.07.2017, 20:28 5
а у меня похожий вопрос. давно хотел узнать, но лень было проверить кодом
итак, в функции
Delphi
1
function Test: TStrings;
нужно ли создавать объект Result? полагаю, что нужно. а нужно ли его уничтожать и в какой момент времени?
0
Айлурофил
469 / 404 / 108
Регистрация: 27.05.2017
Сообщений: 2,333
Записей в блоге: 1
29.07.2017, 22:29 6
Из реальной процедуры:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
function SearchFile(path:string):TStringList;
var SRec:TSearchRec;
....
   Result:=TStringList.Create;
   Result.Clear;
....
end;
....
var lst:TStringList;
...
lst:=SearchFile(fname+'\*.xls');
...
lst.Free;
0
225 / 80 / 35
Регистрация: 01.04.2017
Сообщений: 182
29.07.2017, 23:30 7
Для Delphi IMHO не лучшая практика. Хотя возможно все, особенно когда надо создать 100500 почти одинаковых обьектов.
Зовется это фабрикой (по крайней мере в книжках).
За создание отвечает сама функция, за уничтожение - как правило тот, кто вызвал эту функцию, при этом вызывающий должен убедиться что обьект действительно создан.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Test: TStrings;
begin
  Result := TStrings.Create;
  try
    ... // вытворяем с Result всякие непотребства
  except
    Result.Free;
    raise;
  end;
end;
 
var
  i: TStrings;
begin
  i := Test;
try
  ... // и вновь непотребства, на этот раз с i, который по факту все то-же Result
finally
  i.Free;
end;
Хотя тут есть нюансы. Если со TStrings почти все с владельцем понятно, то к примеру
Delphi
1
function Test: TButton;
уже вызовет вопросы. Кто должен уничтожать: мы ручками, или тот кого мы назначим родителем? Тут правда главное решить, и потом не забыть
Со TStrings почти все - потому как
Delphi
1
2
3
4
5
6
7
8
function Test: TStrings;
begin
...
end;
 
...
 
Form.Caption := Test.Text;
Не вызовет ни одного предупреждения, но утечка памяти гарантирована. Хотя в данном примере это итак очевидно.

Не по теме:

Книга с паттернами (в том числе и фабриками) ISBN 0-201-63361-2 в библиотеке какого-то университета, жаль только что примеры кода на C.

1
5706 / 2297 / 466
Регистрация: 20.11.2009
Сообщений: 7,721
Записей в блоге: 1
30.07.2017, 01:33 8
Цитата Сообщение от DenNik Посмотреть сообщение
нужно ли создавать объект Result? полагаю, что нужно. а нужно ли его уничтожать и в какой момент времени?
естественно надо и создавать и удалять

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

из релаьного проекта могу сказать, что это так ) примерно использовалась конструкция создания нового экземпляра класса так

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function CreateNewClass: TNewClass;
begin
...
  Result := TNewClass.Create;
end;
 
var NewClass: TNewClass;
...
 
begin
NewClass := CreateNewClass;
...
...
// тут работает с NewClass
...
...
// если в конце концов не удаляем NewClass, то гарантированная утечка памяти по адресу, по которому создали экзмепляр
end;
у меня было примерно то, что создавало копию объекта для некого использования и при неудалении, крит был, который я долго вылавливал, от чего он, а крит был, то что память текла от такой конструкции и оно то понятно....

Delphi
1
NewClass := ThewClass.Create;
если не удалить, останется висеть, там тоже самое получается, только более скрытно

и чисто из Си, стал часто пользоваться конструкциями типа "Call By Reference", когда функция ворачивает параметром некий результат имеющий что-то с указателем, тогда меньше недоглядок к утечке памяти, в свое время занялся исследованием "потеков", тут тему создавал даже, но она не приобрела смысла, но для себя же, установил некие правила, как можно или нужно, а как лучше не использовать))
0
пофигист широкого профиля
4754 / 3189 / 861
Регистрация: 15.07.2013
Сообщений: 18,458
30.07.2017, 02:17 9
Цитата Сообщение от Animalia Посмотреть сообщение
Обьекты в Delphi передаются только по указателю (мурзилка, последний абзац). Даже если описать их как const их по прежнему можно редактировать (странно конечно, но факт - компялятор даже предупреждение не выдаст).
Ничего странного. В параметрах функции/процедуры всегда передается число. Либо целое, либо вещественное. Объект не передаётся никогда (если это особо не оговорено).
0
225 / 80 / 35
Регистрация: 01.04.2017
Сообщений: 182
30.07.2017, 08:47 10
Цитата Сообщение от northener Посмотреть сообщение
В параметрах функции/процедуры всегда передается число
С этим никто и не спорит, но вот передаем мы строку, массив или запись (словом нечто что по размеру больше пары регистров) - передается указатель. Но если обьявлено, что это константа - изменить мы эту переменную не сможем. И даже если вызов был stdcall или safecall и по факту мы работаем с дупликатом в стеке - изменить не сможем - компилятор будет выдавать ошибку.
С обьектами такое не пройдет, чтоб создать обьект нужно вызывать конструктор - это я понимаю, тут вопросов нет - проще передать указатель.
Но вот то что мы можем изменять обьект переданый как константу, и это не то что запрещено, а вообще не контролируется - это на мой взгляд финиш. Хотя бы warning выдавался чтоли?
Хотя... как от дурака не защищайся, он всегда найдет способ выстрелить себе в ногу.
0
5860 / 4588 / 1448
Регистрация: 14.04.2014
Сообщений: 20,352
Записей в блоге: 20
30.07.2017, 13:44 11
не объект передается как константа, а указатель на него
так указатель вы и не трогаете обычно
просто делфи для удобства "разыменовывает" указатели
помните recordPtr^.field ? это то же самое
так вот ^ не нужна
recordPtr.field вполне
то же и у объектов

и ни с каким "дупликатом в стеке" вы не работаете
адрес дома сколько не передавай и не копируй, это будет адрес одного и того же дома, пока не построите новый
2
225 / 80 / 35
Регистрация: 01.04.2017
Сообщений: 182
30.07.2017, 22:41 12
Цитата Сообщение от krapotkin Посмотреть сообщение
не объект передается как константа, а указатель на него
так указатель вы и не трогаете обычно
Я говорю не про сам указатель, а про то на что он указывает. Вот смотрите:
Передаем запись и обьект как константу - они оба передаются через указатель.
Delphi
1
2
3
4
5
procedure Test(const AllGood: TForm; const Woops: TMyRec);
begin
  Woops.Left := 0; // О боже! Мы пытаемся изменить константу! Куда катится мир!!!
  AllGood.Left := 0; // Хм, пытаемся изменить константу? Ну... А пофиг, и так сойдет...
end;
При попытке изменить поле записи компилятор выдаст Error E2064 и откажется компилировать, при потытке изменить свойство обьекта - ничего. Вообще ничего: ни Error'a ни Warning'a.
Хотя по идее изменить поле записи = изменить данные в некой области памяти. А изменить свойство обьекта - это вызвать обработчик изменения этого свойства. Тоесть на "мелочь" в виде изменения памяти мы реагируем, а на "непонятные телодвижения" - нет. Черт, да мы можем просто взять и уничтожить обьект, обьект который из серии "смотреть можно, руками не трогать". Как по мне, так крайне не логично.

Цитата Сообщение от krapotkin Посмотреть сообщение
и ни с каким "дупликатом в стеке" вы не работаете
Мурзилка думает иначе
Кликните здесь для просмотра всего текста
Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary.

Google translate
Наборы, записи и статические массивы из 1, 2 или 4 байта передаются как 8-битные, 16-битные и 32-битные значения. Большие наборы, записи и статические массивы передаются в виде 32-разрядных указателей на значение. Исключение из этого правила заключается в том, что записи всегда передаются непосредственно в стек под соглашениями cdecl, stdcall и safecall; Размер пройденной таким образом записи округляется вверх до ближайшей границы двойного слова.

Хотя если честно - сам не проверял. Это из серии "заметки на полях".
0
5706 / 2297 / 466
Регистрация: 20.11.2009
Сообщений: 7,721
Записей в блоге: 1
30.07.2017, 23:05 13
Цитата Сообщение от Animalia Посмотреть сообщение
Передаем запись и обьект как константу - они оба передаются через указатель.
именно, что и нет

Ну так то 2 разные вещи! С TForm - тут константный указатель, мы не можем изменить внутри процедуры адрес самой передаваемой формы, а все свойства, они имеют неконстантный характер в таком случае. Контантой там является именно адрес на TForm.

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

точно так же, нельзя и для первого случая делать
Delphi
1
AllGood := MyNewForm;
будет тоже ошибка, так как мы попытаемся изменить адрес, который изменить нельзя, который мы пометили как константный.

krapotkin как раз это, я так полагаю, и хотел сказать, сообщением выше

вот еще примерчик

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
 
type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;
 
  PMyRec = ^TMyRec;
  TMyRec = record
    X: Integer;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure Test(const F: TForm; const R: PMyRec; const RR: TMyRec);
begin
  F := Form1;     // ERROR
  F.Left := 100;  // OK
  R.X := 100;     // OK
  RR.X := 200;    // ERROR
end;
 
end.
1
Animalia
31.07.2017, 00:06
  #14

Не по теме:

Вон оно как устроено...
На одно недопонимание с Delphi стало меньше. Спасибо за терпение к тугодуму :)

0
northener
31.07.2017, 01:14
  #15

Не по теме:

Цитата Сообщение от Animalia Посмотреть сообщение
На одно недопонимание с Delphi стало меньше.
Лично я так до сих пор это недопонимание так и не разрешил. :)
Поэтому спецификацию/модификатор const при передаче параметра как правило не использую. Я и так знаю что я могу изменять, а что нет. И предупреждение компилятора мне без надобности.

0
5860 / 4588 / 1448
Регистрация: 14.04.2014
Сообщений: 20,352
Записей в блоге: 20
31.07.2017, 08:30 16
const используется еще и для вырезания из кода подсчета ссылок на объект. в старых делфи это только строки, а вот в новых компиляторах для мобил это все объекты

возвращаясь к теме, Arcor все написал правильно,
а получение копии объекта это вообще говоря, вещь автоматически не реализуемая в общем виде
вот у вас
Delphi
1
2
3
4
TMyClass=class
  id:integer;
  name:string;
end;
скопируется без особых проблем
а если так
Delphi
1
2
3
4
5
TMyClass=class
  id:integer;
  name:string;
  parent:TMyClass; // указатель на родителя
end;
тут при копировании нужно указатель на родителя оставить тот что и ранее
Delphi
1
2
3
4
5
TMyClass=class
  id:integer;
  name:string;
  children:TMyClassList; // указатель на потомков
end;
а вот тут при копировании нужно завести новый указатель и новых потомков, которым родителем прописать этот объект
уфф. не слишком сложно для простой операции?
Поэтому в C++ есть даже отдельный класс конструкторов для копирования.
0
31.07.2017, 08:30
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
31.07.2017, 08:30
Помогаю со студенческими работами здесь

Очистка области памяти
Нужно очистить память созданную при помощи new. Сам специализируюсь больше на с++ - но в последнее...

Создание, уничтожение и очистка памяти от динамического массива
Здравствуйте. Создаю динамический массив, задаю размерность через SetLength(). Очищаю через...

Очистка памяти от форм
Мне необходимо почистить память от только что закрытой модальной формы, но так, чтобы при следующем...

очистка памяти
в данном случае деструктор очистит всё, или нет? #include "base.h" #include <cstdlib> #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru