![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с TFileStream
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.
Ну в чем проблема? То что отладчик делфи показывает поля объекта после его освобождения? Так ведь память после освобождения объекта не сразу то затирается.