Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.07.2010, 09:08   #11
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
чрезвычайно чревато.
, возьму на вооружение .


Цитата:
впрочем, не удивлюсь, если сработает и такой механизм:
Код:
  var TS : TString;
...
   TS := функция();
пользуемся TS
после использования:
   TS.Free;
Да, сработает для простого примера, как раз чтобы проверить сработает или нет. Для серьезного проекта с интенсивным выделением и высвобождением памяти, образованием новых экземпляров и т.д. этот код иногда будет вываливаться в Access Violation.
Потому что, память занятая под объекты, после выхода из функции будет помечена как свободная область и есть вероятность, что до использования данного объекта она будет занята кем-то еще. Проблема трудноотлавливаемая плюс в данном случае была рекурсия. Более того, TS Вы разрушите, а кто разрушит Result?
Однозначно лучше процедура с изменяемым входящим параметром. Объект создан до процедуры и соответственно никаких заморочек с его разрушением.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 15.08.2010, 00:22   #12
Anfall
Форумчанин
 
Регистрация: 10.02.2009
Сообщений: 181
По умолчанию

Всем спасибо за ответы.

DomiNick,
Не могли бы объяснить как пользоваться вашей процедурой?
Вот мне надо добавить список найденных файлов в листбокс. При использовании функции я делал так:
ListBox1.Items.AddStrings(GetFiles( 'C:\example'));

Последний раз редактировалось Anfall; 15.08.2010 в 00:28.
Anfall вне форума Ответить с цитированием
Старый 15.08.2010, 01:49   #13
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Сообщение от Utkin Посмотреть сообщение
Да, сработает для простого примера, как раз чтобы проверить сработает или нет. Для серьезного проекта с интенсивным выделением и высвобождением памяти, образованием новых экземпляров и т.д. этот код иногда будет вываливаться в Access Violation.
Рекомендую перестать нести бред. Вы путаете стек и кучу.

Цитата:
Сообщение от Utkin Посмотреть сообщение
Да, только
Код:
Procedure GetFiles_New(Path: String; var Items: TStrings);
var не нужен.

Цитата:
Сообщение от Anfall Посмотреть сообщение
Кто-то сказал, есть утечка памяти в ней.
Да, есть. Но не там, куда вас тыкали две страницы.

Утечка не в этой функции, а в этом коде:

Код:
ListBox1.Items.AddStrings(GetFiles( 'C:\example'));
Надо:

Код:
SL := GetFiles( 'C:\example');
try
  ListBox1.Items.AddStrings(SL);
finally
  FreeAndNil(SL);
end;
А в функции у вас утечка в забытом FindClose.

И в догонку.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.

Последний раз редактировалось Stilet; 16.08.2010 в 09:02.
GunSmoker вне форума Ответить с цитированием
Старый 15.08.2010, 10:31   #14
mutabor
Телепат с дипломом
Старожил
 
Аватар для mutabor
 
Регистрация: 10.06.2007
Сообщений: 4,929
По умолчанию

Цитата:
Result.Free;
Конечно, так делать нельзя. Этим мы убиваем объект, когда функция еще не успела его даже вернуть.

Цитата:
TS Вы разрушите, а кто разрушит Result?
Это в данном случае одно и то же, тот же объект, точнее сказать это ссылки на один и тот же объект.

Цитата:
var TS : TString;
...
TS := функция();
пользуемся TS
после использования:
TS.Free;
Абсолютно нормальный и правильный код, никаких ошибок тут нет.
The future is not a tablet with a 9" screen no more than the future was a 9" black & white screen in a box. It’s the paradigm that survives. (Kroc Camen)
Проверь себя! Онлайн тестирование | Мой блог

Последний раз редактировалось mutabor; 15.08.2010 в 10:37.
mutabor вне форума Ответить с цитированием
Старый 15.08.2010, 14:21   #15
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Сообщение от GunSmoker Посмотреть сообщение
Надо:
Добавлю: по этой причине надо всё же сказать, что это не самый типичный подход. Да, он 100% корректен. Проблема в том, что вы разделяете ответственность за жизнь объекта между вызывающим и вызываемым. Это не самая типичная и прозрачная логика.

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

Соблюдение этого простого правила позволяет вам писать цепочки вложенных вызовов вот так:

Код:
Func1(Func2(Func4), Func3);
Если же функции нужно передать подобную вещь - лучше сделать её процедурой с выходным параметром.

Но в большинстве случаем лучше сработает редизайн API, например:

Код:
procedure GetFiles(const AFiles: TStrings; Path: String; Full: Boolean = False);
var
  Rec:TSearchRec;
  TMP:TStrings;
  ls,ex: String;
  i: integer;
 ok: integer;
begin
  if Path[Length(Path)]<>'\' Then Path:=Path+'\';
  ok := FindFirst(Path+'\*.*',faAnyFile,Rec);
  ... // используем AFiles; обратите внимание, что TStringList.Create нет
end;

begin
  GetFiles(ListBox1.Items, 'C:\example');
end;
И ещё на почитать.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.

Последний раз редактировалось Stilet; 16.08.2010 в 08:54.
GunSmoker вне форума Ответить с цитированием
Старый 15.08.2010, 15:01   #16
mutabor
Телепат с дипломом
Старожил
 
Аватар для mutabor
 
Регистрация: 10.06.2007
Сообщений: 4,929
По умолчанию

Цитата:
Соблюдение этого простого правила позволяет вам писать цепочки вложенных вызовов вот так: Func1(Func2(Func4), Func3);
В Дельфи да, с его необходимостью явно освобождать память, чтобы такое замутить, придется объекты в параметрах передавать. Но если нет необходимости делать вложенные вызовы, то нет ничего плохого если функция будет возвращать объект, часто это удобно.
The future is not a tablet with a 9" screen no more than the future was a 9" black & white screen in a box. It’s the paradigm that survives. (Kroc Camen)
Проверь себя! Онлайн тестирование | Мой блог
mutabor вне форума Ответить с цитированием
Старый 15.08.2010, 16:45   #17
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
Лампочка

До меня кстати дошло... "Items: TStrings" - это ж по сути указатель будет...
Цитата:
Сообщение от Anfall Посмотреть сообщение
DomiNick,
Не могли бы объяснить как пользоваться вашей процедурой?
Вот мне надо добавить список найденных файлов в листбокс. При использовании функции я делал так:
ListBox1.Items.AddStrings(GetFiles( 'C:\example'));
Вот так:

Код:
procedure TForm1.Button1Click(Sender: TObject);
begin
// ListBox1.Visible:=False;
ListBox1.Items.Clear; // очистка (если нужна)
GetFiles_New('C:\example', ListBox1.Items);
// ListBox1.Visible:=True;
end;
Цитата:
Но в большинстве случаем лучше сработает редизайн API, например:
...
GetFiles(ListBox1.Items, 'C:\example');
Ну так у меня как раз примерно так и есть...))

Про FindClose я потом уже таки-вспомнил, вот только не могу найти на каждый ли вызов "FindFirst" нужно "FindClose"... Хотя всё равно придётся...

Anfall, перед последним "end;" в функции добавьте "FindClose(Rec);"...
I am the First of Cyber Evolution...
I am the First to Program your Future...
DomiNick вне форума Ответить с цитированием
Старый 15.08.2010, 17:19   #18
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

это по сути и есть указатель.
в Делфи объекты указательные всегда(всегда указатель на объект, а объект в куче)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 15.08.2010, 18:30   #19
mutabor
Телепат с дипломом
Старожил
 
Аватар для mutabor
 
Регистрация: 10.06.2007
Сообщений: 4,929
По умолчанию

Цитата:
До меня кстати дошло... "Items: TStrings" - это ж по сути указатель будет...
Да что вы говорите

Иногда еще объясняют на таком примере: представьте что у вас на ниточках подвешена коробка, коробка - это объект, ниточки - указатели. Ниточек может быть много, а коробка одна, и вот по одной начинаете перерезать их. Объект будет висеть пока будет хоть одна ниточка, а вот когда обрежется последняя, то тут зависит от языка, в Java например сборщик мусора объект подберет, а в Дельфи перед обрезанием последней ниточки нужно сперва память освободить из под объекта.
The future is not a tablet with a 9" screen no more than the future was a 9" black & white screen in a box. It’s the paradigm that survives. (Kroc Camen)
Проверь себя! Онлайн тестирование | Мой блог
mutabor вне форума Ответить с цитированием
Старый 16.08.2010, 20:04   #20
Anfall
Форумчанин
 
Регистрация: 10.02.2009
Сообщений: 181
По умолчанию

GunSmoker,
Спасибо. Попробую код:
Код:
procedure GetFiles(const AFiles: TStrings; Path: String; Full: Boolean = False);
var
  Rec:TSearchRec;
  TMP:TStrings;
  ls,ex: String;
  i: integer;
 ok: integer;
begin
  if Path[Length(Path)]<>'\' Then Path:=Path+'\';
  ok := FindFirst(Path+'\*.*',faAnyFile,Rec);
  ... // используем AFiles; обратите внимание, что TStringList.Create нет
end;

begin
  GetFiles(ListBox1.Items, 'C:\example');
end;

DomiNick, вот так верно?
Код:
Procedure GetFiles_New(Path: String; Items: TStrings);
Var Rec: TSearchRec; ex: String; ok: Integer;
Begin
If (Path[Length(Path)]<>'\') Then
      Path:=Path+'\';
ok:=FindFirst(Path+'\*.*', faAnyFile,Rec);
While (ok=0) Do
      Begin
      If (Rec.Name<>'.') And (Rec.Name<>'..') Then
            If ((Rec.Attr And faDirectory)<>0) Then
                  Begin
                  GetFiles_New(Path+Rec.Name, Items);
                  End
            Else
                  Begin
                  ex:=ExtractFileExt(Rec.Name);
                  If (ex='.txt') Then
                        Items.Add(Path+Rec.Name);
                  End;
      ok:=FindNext(Rec);
      FindClose(Rec);
      End;

Последний раз редактировалось Anfall; 16.08.2010 в 20:21.
Anfall вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Indy в потоке - утечка памяти PUH Фриланс 5 28.12.2009 14:06
Indy в потоке - утечка памяти PUH Помощь студентам 0 25.12.2009 12:27
Утечка памяти при работе с GDI+ Ivan_32 Общие вопросы C/C++ 2 29.11.2009 00:12
утечка памяти в С++ vengo Общие вопросы C/C++ 9 10.06.2008 21:24
DrawState - утечка памяти? unnamed Win Api 2 11.04.2007 18:36