![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Delphi XE: изменили FreeAndNil?
Masterucs © (2015-08-11 12:29:00)Вот такой код в Delphi XE в SysUtils:
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
Почему он принимает var Obj? Должен по идее TObject.
Нарушается безопасность, ведь все равно он пытается любую ссылку к TObject привести.
Cobalt (2015-08-14 16:40:00) [1]
constructor TBasicAction.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FClients := TList.Create;
end;
destructor TBasicAction.Destroy;
begin
inherited Destroy;
if Assigned(ActionComponent) then
ActionComponent.RemoveFreeNotification(Self);
while FClients.Count > 0 do
UnRegisterChanges(TBasicActionLink(FClients.Last));
FreeAndNil(FClients);
end;
NoUser (2015-08-14 16:33:00) [2]> Cobalt © (14.08.15 16:20) [20]
Проиллюстрируйте, пожалуйста, примерчиком.
Cobalt (2015-08-14 16:20:00) [3]> NoUser © (13.08.15 15:38) [16]
>
> Прямо спрашиваю:
> В каких таких ситуациях мастер позволяет себе отправить
> на освобождение то чего нет?
в деструкторе класса, если в конструкторе возникла исключительная ситуация.
jack128_ (2015-08-14 08:38:00) [4]По хорошему FreeAndNil нужно так переписать
procedure FreeAndNil<T: class>(var Obj: T);
var
Temp: TObject;
begin
Temp := Obj;
Obj := nil;
Temp.Free;
end;
к сожалению дельфи не поддерживает дженерик функции + не работает вывод дженерик параметров для var аргументов.
NoUser (2015-08-13 21:11:00) [5]Игорь Шевченко © (13.08.15 17:44) [17]
То есть, если в том коде, который написан мастером, все вызовы Obj.Free заменить на Obj.Destroy то можно не опасаться за стабильность работы программы?
К чему это я - да к тому, что если кто-то находит/приводит серьезные аргументы не в пользу FreeAndNil, а при этом сам напрямую не вызывает Destroy - значит он лукавит.
Игорь Шевченко (2015-08-13 17:44:00) [6]NoUser © (13.08.15 15:38) [16]
Таких ситуаций не существует...
NoUser (2015-08-13 15:38:00) [7]Почему намёках, - конкретные вопросы то.
> Проверка на nil в данном случае (по мнению мастера, читающего
> справку) нужна, чтобы избежать исключенияAccess Violation.
Прямо спрашиваю:
В каких таких ситуациях мастер позволяетсебе отправить на освобождение то чего нет?
Игорь Шевченко (2015-08-13 10:54:00) [8]NoUser © (12.08.15 23:17) [14]
Ты если чего хочешь сказать, говори прямо, а то в твоих намеках можно еще две страницы смысл искать. Проверка на nil в данном случае (по мнению мастера, читающего справку) нужна, чтобы избежать исключения Access Violation.
NoUser (2015-08-12 23:17:00) [9]
> Free verifies that the object reference is not nil before
> calling Destroy
А спрашивает ли себя мастер, читающий справку, зачем же предпроверка на нил?
Игорь Шевченко (2015-08-12 23:11:00) [10]NoUser © (12.08.15 22:32) [12]
> А многие ли из мастеров вызывают именно Destroy вместо Free
> ?
Многие из мастеров читают справку, в которой написано:
"Do not call Destroy directly. Call Free instead. Free verifies that the object reference is not nil before calling Destroy. "
Впрочем, давайте дальше про ARC смотреть:
function TObject.__ObjRelease: Integer;
begin
Result := AtomicDecrement(FRefCount) and not objDisposedFlag;
if Result = 0 then
begin
__MarkDestroying(Self);
if __SetDisposed(Self) then
Destroy
else
FreeInstance;
end;
end;
В результате вызовется тот же Destroy при необходимости.
NoUser (2015-08-12 22:32:00) [11]Игорь Шевченко © (12.08.15 21:39) [11]
Спасибо, принимается, прочитал и вспомнил свои похожие мысли/сомнения, в момент первого знакомства с данным функционалом.
Мой велосипед хочет показать любителям фриониливания, что есть еще и динамически выделяемая память (а не только объекты), и потоки, и 'фрифобные' объекты.
Но если копнуть дальше:
procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
if Self <> nil then
Destroy;
{$ENDIF}
end;
то возникает следующий вопрос:
А многие ли из мастеров вызывают именно Destroy вместо Free ?
Игорь Шевченко (2015-08-12 21:39:00) [12]NoUser © (12.08.15 13:28) [8]
Моя версия полностью совпадает с изложенной тут:
http://www.nickhodges.com/post/Using-FreeAndNil.aspx
NoUser (2015-08-12 20:30:00) [13]Внимание! Пост направлен на обоснование моейточки зрения :D Просьба все негативные проклятия изливать где-то ещё ;)))))
Да простит меня многоуважаемый GunSmoker за такой вот ответ Игорю Шевченко © :
Это ремни безопасности, которые нужно и уже можно использовать всегда, и чтобы меньше печатать.
)))
K-1000 (2015-08-12 19:35:00) [14]
> NoUser © (12.08.15 13:28) [8]
>
> Непременно Вам расскажу, если узнаю Вашу версию необходимости
> FreeAndNil.
Вопрос не ко мне, но отвечу:
http://www.gunsmoker.ru/2009/04/freeandnil-free.html
NoUser (2015-08-12 13:28:00) [15]Непременно Вам расскажу, если узнаю Вашу версию необходимости FreeAndNil.
Игорь Шевченко (2015-08-12 13:18:00) [16]NoUser © (11.08.15 23:40) [6]
А зачем этот велосипед, тем более, с такими кондовыми именами ?
NoUser (2015-08-11 23:40:00) [17]FreeAndNil, конечно, крутая штука, но мне она как-то сразу не понравилась...
TFreeOrReleaseProc = procedure of object;
procedure FrezMem(var Ptr); inline;
procedure FrezObj(var Obj); overload; inline;
procedure FrezObj(var Obj; FreeOrReleaseProc :TFreeOrReleaseProc); overload; inline;
//-------------------------------------------------------------------------------
procedure FrezMem(var Ptr);
begin
FreeMem(AtomicExchange(Pointer(Ptr), nil));
end;
procedure FrezObj(var Obj);
begin
TObject(AtomicExchange(Pointer(Obj), nil)).Free;
end;
procedure FrezObj(var Obj; FreeOrReleaseProc :TFreeOrReleaseProc);
begin
if ( AtomicExchange(Pointer(Obj), nil) <> nil ) then FreeOrReleaseProc;
end;
//-------------------------------------------------------------------------------
FrezObj(Form, Form.Release);
// or
FrezObj(IoCpSocket, IoCpSocket.Release);
Kerk (2015-08-11 13:46:00) [18]
> var параметр должен быть identical...
Ну вот и ответ почему оно сделано так, как сделано :)
brother (2015-08-11 13:31:00) [19]> Должен по идее TObject.
ээээ, с чего бы? только потому, что все остальные потомки?
Masterucs (2015-08-11 13:02:00) [20]
> Попробуй написать аналог с TObject
var параметр должен быть identical...