Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблема с TFileStream


Страницы:   1 2 3 4 5

ProgRAMmer Dimonych ©   (2007-11-05 22:45:00) 

Сталкивался много раз, сейчас решил разобраться :)

Дело в том, что TFileStream как-то странно себя ведёт. Даже, я бы сказал, непредсказуемо, т.е. не так, как должен был бы.

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

Tmp:TFileStream;

Забавно то, что в начале процедуры этот самый Tmp показывается (в Delphi'овом Hint'е) со свойством (Handle:12) и таким же остаётся после вызова его метода Free. То же самое с FileStream'ом, который блокирует файл до тех пор, пока он нужен моему объекту, и который объявлен как поле объекта.

Самое печальное, что, похоже, именно из-за такого поведения возникают AV и External Errors. Посмотрел исходник TFileStream'а и справку по Дельфям: в деструкторе TFileStream'а вызывается функция FileClose, которая, если верить справке, просто принимает Handle файла, что, на мой взгляд, имеет печальные последствия:

destructor TFileStream.Destroy;
begin
 if FHandle >= 0 then FileClose(FHandle);
 inherited Destroy;
end;


Т.е. FHandle передаётся не как var-параметр, а inherited Destroyтянется аж от TObject, где он virtual.

Попробовал копнуть в сети, но русскоязычного ничего не нашёл. Насколько мне позволяет судить моё знание английского, что-то по этой проблеме есть здесь: http://www.delphipraxis.net/topic77280.html.Если я правильно понимаю немецкий, то вместо метода Free следует юзать процедуру FreeAndNil().

Это так?


ProgRAMmer Dimonych   (2007-11-05 23:29:00) [81]

> Юрий Зотов ©   (05.11.07 23:24) [6]

Вы меня опередили. Но по этому куску кода без FreeAndNil - никуда. Так ведь? Ну, если не считать саморучно написанной замены.


vpbar   (2007-11-05 23:28:00) [82]

жуть


ProgRAMmer Dimonych   (2007-11-05 23:27:00) [83]

ОК, даю кусок кода...

function TMyObject.SaveToFile(FileName:ANSIString):Boolean;
var
Tmp:TFileStream;
FN:ANSIString;
i:Integer;
N:Word;
begin
Result:=False;
FN:=TempDir+ExtractFileName(FileName)+'~';
DeleteFile(PANSIChar(FN));
try Tmp:=TFileStream.Create(FN,fmCreate); except Exit; end;
{Пишем в файл}
if Assigned(Tmp) then Tmp.Free;
===>>> if Assigned(FFile) then FFile.Free; {Здесь вызывается Free}
if FFileName=FileName then DeleteFile(PANSIChar(FFileName));
RenameFile(FN,FileName);
Self.LoadFromFile(FileName);
Result:=True;
end;

function TMyObject.LoadFromFile(FileName:ANSIString):Boolean;
var
N:Word;
i:Integer;
begin
Result:=False;
===>>> if Assigned(FFile) then FFile.Free; {А здесь у нас AV}
{Чтение файла, которого нет из-за AV}
end;


Что скажете?


Юрий Зотов   (2007-11-05 23:24:00) [84]

> ProgRAMmer Dimonych ©   (05.11.07 23:12) [3]

> как правильно удалять TFileStream?

Точно так же, как и ЛЮБОЙ другой объект - вызовом Free.

Если при удалении объекта нужно еще и обнулить какую-то переменную, то можно вызвать FreeAndNil. Она выполнит 2 операции - и объект уничтожит (тем же вызовом Free), и переменную обнулит. Причем это ДВЕ совершенно РАЗНЫЕ операции. Их можно выполнить и самому, ручками.


Юрий Зотов   (2007-11-05 23:17:00) [85]

> что, на мой взгляд, имеет печальные последствия

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

Ну и что? Какие же тут печальные последствия?


Anatoly Podgoretsky   (2007-11-05 23:16:00) [86]


> Если объект удалён, то вместо Объект=(Свойство:Значение;
>  Свойство:Значение) там должно по идее отображаться Объект=nil.
>

А все ветки об этом говорят, что это ересь и блажь.


ProgRAMmer Dimonych   (2007-11-05 23:12:00) [87]

> vpbar ©   (05.11.07 22:58) [1]
> Ну в чем проблема? То что отладчик делфи показывает поля
> объекта после его освобождения? Так ведь память после освобождения
> объекта не сразу то затирается.

Да вот ведь вещь: не всегда так, иногда nil. Но это, наверное, не основное. Хотя какое не сразу? Если объект удалён, то вместо Объект=(Свойство:Значение; Свойство:Значение)там должно по идее отображаться Объект=nil.

> homm ©   (05.11.07 23:02) [2]
> > [0] ProgRAMmer Dimonych ©   (05.11.07 22:45)
> А при чем здесь TFileStream?

По приведённой мной ссылке - ветка форума, где, насколько я могу судить, пытаясь вникнуть в суть написанного на незнакомом мне языке, обсуждается проблема использования функции Assigned() по отношению к экземпляру TFileStream. Вроде как вечно True возвращает, а это уже грозит AV'ами и прочими радостями. Если сформулировать мой вопрос "в лоб", то: как правильно удалять TFileStream?


homm   (2007-11-05 23:02:00) [88]

> [0] ProgRAMmer Dimonych ©   (05.11.07 22:45)
> Если я правильно понимаю немецкий, то вместо метода Free
> следует юзать процедуру FreeAndNil().

А при чем здесь TFileStream?


vpbar   (2007-11-05 22:58:00) [89]


> Забавно то, что в начале процедуры этот самый Tmp показывается
> (в Delphi'овом Hint'е) со свойством (Handle:12) и таким
> же остаётся после вызова его метода Free.

Ну в чем проблема? То что отладчик делфи показывает поля объекта после его освобождения? Так ведь память после освобождения объекта не сразу то затирается.


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо