Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Вниз

FreeAndNil   Найти похожие ветки 

 
Ш-К   (2004-04-30 11:55) [0]

Объясните действие этой процедуры.
Смотрю по исходникам DevExpress, никак не въеду, почему в одних местах .Free, а в других FreeAndNil.

procedure FreeAndNil(var Obj);
var
 Temp: TObject;
begin
 Temp := TObject(Obj);
 Pointer(Obj) := nil;
 Temp.Free;
end;


 
Гаврила ©   (2004-04-30 11:58) [1]

Я ее не использую. Опасно. Проще написать аналог двумя строками

var O: TObject;

..
O.Free;
O:=nil;


 
Тимохов ©   (2004-04-30 11:58) [2]

1. Если нужно, чтобы после дестроя указатель на объект стал равен nil, то нужно вызывать freeandnil. Если это не важно, достаточно вызвать просто free. Почему в devexpress в одних местах free, а в других freeandnil - сказать сложно - значит так нужно по логике работы.

2. По телу процедуры. Что здесь не ясно? Сначала обнуляется переданное значение, затем вызывается деструктор.


 
Тимохов ©   (2004-04-30 12:00) [3]


> Гаврила ©   (30.04.04 11:58) [1]


> Опасно. Проще написать аналог двумя строками

Как любит писать Игорь Шевченко - вы бы употребляли словосочетание имхо в таких случаях.

Чем же опасно? ФАкты!


 
Ш-К   (2004-04-30 12:16) [4]

Я думал, что деструктор в nil ставит автоматом.
Оказалось, что нет. Значит я неправильно понимаю работу деструктора.
Зачем нужен указатель после дестороя?


 
Тимохов ©   (2004-04-30 12:19) [5]


> Ш-К   (30.04.04 12:16) [4]

Нафиг не нужен.
Но не всегда можно удалить указатель.

Например:
function Get: TObject;
begin
  Result := ...
end;

Get.Free();

Вполне возможный код. Что вы здесь удалять будете? Функцию get?


 
panov ©   (2004-04-30 12:26) [6]

Зачем нужен указатель после дестороя?

Для простейшей проверки на существование объекта.


 
Ш-К   (2004-04-30 12:53) [7]

Тимохов ©   (30.04.04 12:19) [5]
Не убедительно.

function Get: TObject;
begin
 Result := GlobalObject
end;

Get.Free я буду удалять GlobalObject.

panov ©   (30.04.04 12:26) [6]

> Для простейшей проверки на существование объекта.

Это как?


 
Плохиш   (2004-04-30 12:56) [8]

>Ш-К   (30.04.04 12:53) [7]
Тогда такой пример:

A:=TObject.Create;
...
B:=A;
...
C:=B;
...
D:=A;
...
D.Free;

Какой указатель на объект должен обнилить Destructor?


 
Тимохов ©   (2004-04-30 12:59) [9]


> Ш-К   (30.04.04 12:53) [7]
> Тимохов ©   (30.04.04 12:19) [5]
> Не убедительно.

Не всем дано быть убежденным.


 
Ш-К   (2004-04-30 13:14) [10]

Плохиш   (30.04.04 12:56) [8]
Здесь понятно.

Теперь поднимаю вопрос.
Если объект разрушен, а указатель не nil, как я по указателю могу определить, что объест разрушен.
Ведь постоянно вижу в коде:
if Assigned(Obj) then Obj.Do;


 
panov ©   (2004-04-30 13:17) [11]

>Ш-К   (30.04.04 12:53) [7]

...
var
 MObj: TMyObject;

implementation

...

procedure TForm1.Button1Click(Sender: TObject);
begin
 if not Assigned(MObj) then MObj := TMyObject.Create;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 FreeAndNil(MObj);
end;


 
Плохиш   (2004-04-30 13:17) [12]


> Если объект разрушен, а указатель не nil, как я по указателю
> могу определить, что объест разрушен.

По указателю - никак.


 
Игорь Шевченко ©   (2004-04-30 13:25) [13]

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

с FreeAndNil тоже самое.


 
Гаврила ©   (2004-04-30 13:28) [14]


> Как любит писать Игорь Шевченко - вы бы употребляли словосочетание
> имхо в таких случаях.


В процессе разработки объект был заменен на интерфейс.
Компилятор великолепно пропустил такую конструкцию. О результатах можно догадаться.
Туда вообще можно что угодно подставить. Почему не объявили тип параметра TObject - мне не понятно.


 
Ш-К   (2004-04-30 13:45) [15]

Гаврила ©   (30.04.04 13:28) [14]

> Почему не объявили тип параметра TObject - мне не понятно

Они это вынесли в Help :)

Из прочитанного подвожу для себя итог.
Поскольку после деструктора указатель никогда нахрен не нужен, убивать объект исключительно FreeAndNil (ну, если он идентификатор имеет).


 
Mim1 ©   (2004-04-30 14:01) [16]

Гаврила ©   (30.04.04 13:28) [14]

Выходит сама freeandnil нисколько не опасна, а опасна она при неправильном использовании, так что слово "имхо" очень дажу уместно.

Может если меняется обьект на интерфейс, то и стоит предусмотреть такую проблемму, а не разводить руками и пинять на борланд.


 
Гаврила ©   (2004-04-30 14:17) [17]

>>Mim1 ©   (30.04.04 14:01) [16]

Под опасностью я подразумеваю вероятность ошибки прогрпммиста. Это совершенно объективный фактор ,и он должен учитываться. Иначе, наприме,рне имела бы смысла секция private, как тут обсуждалось в другой ветке
Имеем тот самый случай, когдла произошла ошибка программиста. При использовании просто Free компилятор бы сразу разъяснил, в чем я не прав.
Поскольку все мы знаем, что изменения приходится вносить постоянно.


> Поскольку после деструктора указатель никогда нахрен не
> нужен, убивать объект исключительно FreeAndNil


Если указатель локальный, и после разрушения он сразу выходит из области видимости, наверно FreeAndNil уж точно не нужен. Видимо для каждого случая надо действовать по разному


 
Гаврила ©   (2004-04-30 14:21) [18]


>
> Они это вынесли в Help :)


Что-то не нашел я там объяснений по поводу отсутствия типизации


 
Тимохов ©   (2004-04-30 14:23) [19]


> Гаврила ©   (30.04.04 13:28) [14]
> Туда вообще можно что угодно подставить. Почему не объявили
> тип параметра TObject - мне не понятно.

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

Автору вопроса.
Вывод про постоянно использование freeandnil поспешен.
К тому же у вас не всегда это получится сделать.
Например, freeandnil(get) из моего примера не скомпилится.


 
Гаврила ©   (2004-04-30 14:28) [20]


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


Позор на мою седую голову :-(((((((


 
Тимохов ©   (2004-04-30 14:32) [21]


> Гаврила ©   (30.04.04 14:28) [20]

Был Гаврила программистом
Гаврила фри энд нил юзАл...

Я вообще тоже не пользуюсь freeandnil, но по другим соображенями - считаю, что у любой локальной задачи должно одно единственное решение - в данном случае это Free, затем := nil (имхо и еще раз имхо). Когда для одной и тойже задачи в разных местах используется разный механизм - при просмотре кода всегда возбуждает вопросы - а на фига... (имхо и еще раз имхо).


 
Ш-К   (2004-04-30 14:33) [22]

Тимохов ©   (30.04.04 14:23) [19]
Или With Create... синтаксически невозможно.
Значит надо деструкторы попереписать, чтоб обнулялось.

Гаврила ©   (30.04.04 14:21) [18]
Объяснений нет, есть Warning.

Плохиш   (30.04.04 13:17) [12]

> По указателю - никак.

function AssignedObj(Obj: TObject): Boolean;
var
   TempStr: string;
begin
   Result := True;
   try
     TempStr := Obj.ClassName;
   except
     Result := False;
   end;
end;

О как.


 
Тимохов ©   (2004-04-30 14:37) [23]


> Ш-К   (30.04.04 14:33) [22]

ваш код выбросьте нафиг, или затолкайте куда-нибудь.
Он с равной вероятностью для дохлой ссылки может вернуть и true и false.

Запомните аксиому - по ссылке 100% НЕЛЬЗЯ точно понять живая она или нет.


 
Гаврила ©   (2004-04-30 14:37) [24]

>>Ш-К   (30.04.04 14:33) [22]
>>function AssignedObj(Obj: TObject): Boolean;

Никогда так не делай


> Был Гаврила программистом
>Гаврила фри энд нил юзАл...


А вот и не юзал. Клевета :-)


 
Игорь Шевченко ©   (2004-04-30 14:42) [25]

Я использую FreeAndNil. Иногда, когда удобно использовать именно эту функцию :)


 
Ш-К   (2004-04-30 14:45) [26]


> Он с равной вероятностью для дохлой ссылки может вернуть
> и true и false.

Отдельную ветку создать? Или объясните: почему?


 
Гаврила ©   (2004-04-30 14:47) [27]

procedure FreeAndNil(var Obj: TObject);
begin
 Obj.Free;
 Obj:=nil;
end;

...
FreeAndNil(TObject(Form1));

В приципе можно так...


 
Тимохов ©   (2004-04-30 14:49) [28]


> Ш-К   (30.04.04 14:45) [26]

Запомните аксиому - в свое время сами все поймете.


 
Гаврила ©   (2004-04-30 15:13) [29]


> Гаврила ©   (30.04.04 14:47) [27]



> В приципе можно так...


Блин, пятница, голова в отключке. Это же тоже самое, тот же "опасный код".
Все, пора отдыхать и расслабляться


 
sniknik ©   (2004-04-30 15:16) [30]

Ш-К   (30.04.04 14:45) [26]
> Отдельную ветку создать? Или объясните: почему?
free только освобождает память но не чистит ее, пока ее никто не занял и заполнил своими указатель будет указывать на "правильные" данные для "убитого" уже обьекта.


 
oleg_art   (2004-04-30 15:43) [31]

To sniknik:
  Free освобожает память и заполняет её нулями.


 
Тимохов ©   (2004-04-30 15:46) [32]


> oleg_art   (30.04.04 15:43) [31]

нет


 
Юрий Зотов ©   (2004-04-30 15:49) [33]

> Ш-К   (30.04.04 14:45) [26]

> Отдельную ветку создать? Или объясните: почему?

На один и тот же объект может иметься хоть 100 внешних ссылок. Но ни об одной из них самому объекту, естественно, ничего не известно. Как же может метод Free обнулить хотя бы одну? Тем более, все?

Пример.

var
 A, B: TObject;
begin
 A := TObject.Create; // Первая ссылка
 B := A; // Вторая ссылка

// Внимание, вопрос! Класс TObject написан программистами
// Borland. Может ли созданный мною экземпляр этого класса знать
// о том, что где-то в моей программе сужествуют какие-то там
// переменные A и B, которые на него ссылаются?
 A.Free; // Обе ссылки стали битыми, но не изменились.
// Внимание, еще вопрос! Мог ли метод Free класса TObject, тоже
// написанный программистами Borland, обнулить переменную A,
// о которой он и понятия не имел? А переменную B?
end;

> Тимохов

На FreeAndNil мы тоже налетали. Там были какие-то тонкости (не помню уже, в чем суть), но в итоге причина ошибки оказалась в том, что во FreeAndNil СНАЧАЛА обнуляется ссылка, а уже ЗАТЕМ уничтожается объект (вероятно, поэтому ее следовало бы назвать NilAndFree). В результате мы написали свою процедурку, которая делала именно сначала Free, потом обнуление - и все сразу же встало на место.


 
Плохиш   (2004-04-30 15:52) [34]


> oleg_art   (30.04.04 15:43) [31]
> To sniknik:
>   Free освобожает память и заполняет её нулями.

Хоть бы в генофонд для начала заглянул :-(


 
oleg_art   (2004-04-30 16:56) [35]

Вопрос  Тимохову:
 Т.е. вы хотите сказать, что после освобождения экземпляра класса ссылка остается валидная и она указывает на то же адрес,
только по этому адресу теперь размещается мусор ?


 
Anatoly Podgoretsky ©   (2004-04-30 17:07) [36]

oleg_art   (30.04.04 16:56) [35]
Не обязательно мусор, это могут быть старые данные, это могут новые данные, но действительные, это могут новые данные, но не действительные, это может быть мусор.

Единственно общее для всех случаев, это то что ссылка недействительная, в твоей терминологии не валидная


 
oleg_art   (2004-04-30 17:19) [37]

To Podgoretsky:
Я под валидной ссылкой понимал, что Assigned(vPointer)=true.
Насколько я вас понял, вы под действительностью ссылки понимаете
то, что ссылка указывает на первый байт, где после этого в размещаются данные класса ?


 
Тимохов ©   (2004-04-30 17:19) [38]


> oleg_art   (30.04.04 16:56) [35]

Слушайте АП.
Мне нечего добавить к его словам.


 
Тимохов ©   (2004-04-30 17:20) [39]


> Я под валидной ссылкой понимал, что Assigned(vPointer)=true.

очень плохо


 
WebErr ©   (2004-04-30 17:24) [40]

Дядька Краснов в своей книге DirectX для Delphi вообще использовал такое освобождение: SomeObject := nil;
Дескать обнулю указатель - Delphi сама освободит память.


 
Тимохов ©   (2004-04-30 17:25) [41]


> WebErr ©   (30.04.04 17:24) [40]

думаю там были интерфейсы.
там это верно.


 
Fay ©   (2004-04-30 17:25) [42]

2oleg_art   (30.04.04 17:19) [37]
Вы же не допускаете, что АП имет ввиду ярлык на рабочем столе c с надписью "TObject"?


 
WebErr ©   (2004-04-30 17:28) [43]


> Тимохов ©   (30.04.04 17:25) [41]

Спасибо (без приколов)


 
Юрий Зотов ©   (2004-04-30 17:29) [44]

> oleg_art   (30.04.04 17:19) [37]

Assigned всего лишь делает проверку на nil и все, что не nil, дает True. Сами прикиньте - а что она еще может сделать? И посмотрите [33].


 
Тимохов ©   (2004-04-30 17:29) [45]


> WebErr ©   (30.04.04 17:28) [43]

Так я что, прав, там были интерфейсы? (также без приколов)


 
oleg_art   (2004-04-30 17:30) [46]

TO Fay:
Нет.
 Я хочу у АП узнать, что он понимает под действительностью ссылки. То что я сказал или другое ?


 
WebErr ©   (2004-04-30 17:31) [47]

Кстати, вот пример для первокурсников:

var
 P, Q: PInteger;
begin
 New(P);
 Q := P;
 Q^ := 100;
 Dispose(P);
 if P^ = 100 then
   ShowMessage("Hi!");
end;


 
WebErr ©   (2004-04-30 17:33) [48]


> Тимохов ©   (30.04.04 17:29) [45]

Там были COM объекты DirectDraw7 и DirectDraw.
Хотя я ещё доиа посмотрю, он вроде бы не только с ними так обращался, но и с TBitmap"ом, хотя не уверен.


 
Тимохов ©   (2004-04-30 17:34) [49]


> WebErr ©   (30.04.04 17:33) [48]

если com объекты, то можно просто писать nil (а можно вообще не писать).


 
Юрий Зотов ©   (2004-04-30 17:54) [50]

> oleg_art   (30.04.04 17:30) [46]

Под валидностью ссылки понимается (не только АП, а вообще) то, что она указывает именно на то, на что и должна указывать.

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



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.034 c
1-1083674882
Girder
2004-05-04 16:48
2004.05.16
Как быстро удалить указатель из списка


4-1080290585
Абульфаз Ильчибей
2004-03-26 11:43
2004.05.16
Странная функция MoveFileEx.


1-1083403477
k@rt
2004-05-01 13:24
2004.05.16
TListItem.Data


14-1083132720
Pomoshnik
2004-04-28 10:12
2004.05.16
Delphi


14-1082899941
Piter
2004-04-25 17:32
2004.05.16
Wine





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский