![]() |
| ||
|
|
Новости |
Поиск |
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().
Это так?
Юрий Зотов (2007-11-06 01:45:00) [41]> korneley © (06.11.07 01:38) [48]
А что тут странного или плохого? У меня, скажем, нет абсолютно никаких способностей к рисованию - ну так я и в художники не лезу, и обиженным себя нисколько не чувствую. Люди все разные, кому-то быть художником, кому - программистом, кому - певцом. И ничего странного, и ничего плохого.
korneley (2007-11-06 01:38:00) [42]
> Юрий Зотов © (06.11.07 01:14) [47]
Как занятно эволюционировала ветка... Начали с использования указателей на объекты, а закончили (?) рекомендациями кому и чем следует заниматься :) Да, всетаки "неблагодарное это занятие - бить красных..." (с)
Юрий Зотов (2007-11-06 01:14:00) [43]> ProgRAMmer Dimonych © (06.11.07 00:27) [38]
> Компилятор нагрузить этим делом.
> vpbar © (06.11.07 00:28) [39]
> Компилятор добавит нужную информацию.
Вы представляете себе, что это будет за компилятор? Сложность его? Скорость его? Надежность его?
И объект, хранящий адреса всех ссылок на себя - Вы представляете, насколько увеличится объем занимаемой им памяти? Понимаете, что память эту придется еще и постоянно перераспределять (количество ссылок ведь меняется)? Что это будут серьезные тормоза, что увеличится фрагментированность памяти?
И главное - а зачем ве это? Чтобы люди, не понимающие, что такое указатель, тоже могли программировать? А на фига? Планете нужны не только программисты.
На крайняк - пусть юзают интерфейсы, пусть пишут на джаве или под дотнетом. Программирование на уровне адресов - не для них.
korneley (2007-11-06 01:10:00) [44]
> Ни что не мешает, кроме защищенного режима
Не, ну своей переменной типа TObject, я могу присвоить всё, что угодно (а потом удивляться результатам), не взирая ни на что, тем более на "защищенный режим".
Германн (2007-11-06 01:06:00) [45]
> korneley © (06.11.07 00:49) [44]
>
>
> > Ндя, если присваивать переменной типа TObject число -
> это
> > точно ошибка в геноме.
> А что мешает? В сысле не генома, а присвоения? Что хотим,
> то и храним в отведённых нам 32-х разрядах.
Ни что не мешает, кроме защищенного режима.
korneley (2007-11-06 00:49:00) [46]
> Ндя, если присваивать переменной типа TObject число - это
> точно ошибка в геноме.
А что мешает? В сысле не генома, а присвоения? Что хотим, то и храним в отведённых нам 32-х разрядах. Хоть четыре восьмибитных символа. Если правила позволяют - значит можно. Или ни разу не использовалиTString.Objects[i] := TObject(<целое число>);?
vpbar (2007-11-06 00:39:00) [47]>>korneley © (06.11.07 00:37) [42]
Ндя, если присваивать переменной типа TObject число - это точно ошибка в геноме.
korneley (2007-11-06 00:37:00) [48]
> vpbar © (06.11.07 00:13) [33]
> Добавить в объект указатель на список ссылок на переменные
Пусть даже имеется "внутренний", только для системы "ССП". Как отследить все перемещения/присвоения ссылок и отличить их, скажем, от арифметических операций? b := $01234567; это адрес или нет?
>А ведь их может быть и не одна, запросто
> Вот это некоторая проблема
:))) Некоторая... :))) И не единственная... :))) Кроме ошибки в коде... генетическом...
ProgRAMmer Dimonych (2007-11-06 00:33:00) [49]> vpbar © (06.11.07 00:31) [40]
> ЗЫ. Видимо пора спать, чтобы червь сомнений не мутил мой
> светлый разум. :)
Червь - не самое страшное. Вон троянцы тоже спали, а в это время троянский конь сработал. :)
vpbar (2007-11-06 00:31:00) [50]Юрий, я уже начинаю сомневатся в своей правоте :) Хотя и не привык слепо верить авторитетам. Просто не пойму, что тут фантастичного.
ЗЫ. Видимо пора спать, чтобы червь сомнений не мутил мой светлый разум. :)
vpbar (2007-11-06 00:28:00) [51]>>Юрий Зотов © (06.11.07 00:24) [36]
Гм. А как объект знает какого он типа? И какую виртуальную функцию надо вызывать?
Компилятор добавит нужную информацию.
ProgRAMmer Dimonych (2007-11-06 00:27:00) [52]> Юрий Зотов © (06.11.07 00:24) [36]
> Каким образом объект в своем конструкторе может узнать о
> том, что где-то там вообще существует какая-то переменная
> a?
>
> Тем более, узнать ее адрес.
> Юрий Зотов © (06.11.07 00:25) [37]
> > > vpbar © (06.11.07 00:13) [33]
> b:=a; // добавляем ссылку на b в ССП
> А это и тем более фантастика.
Компилятор нагрузить этим делом. Ну, в смысле этот, как его? Который про адреса переменных всё знает? Линковщик. :)
Юрий Зотов (2007-11-06 00:25:00) [53]> > vpbar © (06.11.07 00:13) [33]
b:=a; // добавляем ссылку на b в ССП
А это и тем более фантастика.
Юрий Зотов (2007-11-06 00:24:00) [54]> vpbar © (06.11.07 00:13) [33]
a:=TObject.Create; // в том числе добавляем ссылку на a в ССП
КАК?
Каким образом объект в своем конструкторе может узнать о том, что где-то там вообще существует какая-то переменная a?
Тем более, узнать ее адрес.
vpbar (2007-11-06 00:16:00) [55]>>ProgRAMmer Dimonych © (06.11.07 00:14) [34]
>В COM, кажется, так делается?
Ага. В делфи, тоже, но только для интерфейсов.
ProgRAMmer Dimonych (2007-11-06 00:14:00) [56]> Юрий Зотов © (06.11.07 00:03) [28]
Не беспокойтесь Вы так, общее представление у меня есть. Скорее всего, с толку сбило то, что обычно не пользуюсь вот такими межпроцедурными вещами типа FFile в этом случае. Т.е. обычно Tmp:=TStringList.Create; в начале процедуры и Tmp.Free; в конце - и всё классно. А тут чего-то просто не подумал.
> vpbar © (06.11.07 00:03) [29]
> Ну тогда ссылки считать, и не освобождать пока все ссылки
> не обнулятся.
В COM, кажется, так делается?
===
А вообще - всем спасибо, по моему вопросу - всё.
vpbar (2007-11-06 00:13:00) [57]
> Юрий Зотов © (06.11.07 00:07) [30]
> А каким-таким волшебным образом в методе Free объекта можно
> узнать о том, что такая переменная вообще существует?
Передавать в free указатель на переменную.
>>А ведь их может быть и не одна, запросто.
Вот это некоторая проблема.
Как вариант. Добавить в объект указатель на список ссылок на переменные (далее ССП).
var a,b,c:TObject;
....
a:=TObject.Create; // в том числе добавляем ссылку на a в ССП
b:=a; // добавляем ссылку на b в ССП
....
c:=b; // добавляем ссылку на c в ССП
b:=nil ; // удаляем ссылку на b из ССП
c.free; // освобождаем и обнуляем все ссылки из ССП
//
Про многопоточность думать еще надо. Хотя тоже решаемо.
Германн (2007-11-06 00:13:00) [58]
> Юрий Зотов © (06.11.07 00:03) [28]
А с телефонной книжкой разъяснение было интереснее :-)
korneley (2007-11-06 00:10:00) [59]
> С объектом связть список. В который добавлять указатель
> на переменную при присваивании объекта.
"Догнать Савранского - это утопия..." (с) :)
Юрий Зотов (2007-11-06 00:07:00) [60]vpbar © (05.11.07 23:52) [25]
> Ничего сложного для разработчиков.
В самом деле? Тогда один простенький вопросик можно? А каким-таким волшебным образом в методе Free объекта можно узнать о том, что такая переменная вообще существует?
А ведь их может быть и не одна, запросто.