Текущий архив: 2006.11.12;
Скачать: CL | DM;
ВнизFree and nil Найти похожие ветки
← →
Сатир (2006-10-23 12:58) [0]Тут на новой работе достался по наследству код, и в нём попалась такая конструкция
freeandnil(fImportExcelNakl), где fImportExcelNakl наследник от TForm;
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
Почему нельзя просто написать:
fImportExcelNakl.Free;
fImportExcelNakl:=nil; ?
← →
Плохиш © (2006-10-23 12:59) [1]
> Почему нельзя просто написать
А что там прямо такой запрет стоит?
← →
umbra © (2006-10-23 13:02) [2]можно. но это будет 2 строчки, а не одна :)
← →
Сатир (2006-10-23 13:02) [3]
> А что там прямо такой запрет стоит?
запрета нету. Есть интерес, почему нужно было так усложнять освобождение и обнуление экземпляра формы?
Может мой вариант не будет выдавать такой же результат, как и предыдущий?
← →
Курдль © (2006-10-23 13:04) [4]
> umbra © (23.10.06 13:02) [2]
> можно. но это будет 2 строчки, а не одна :)
Вот именно! :) Я тоже всегда пользовался FreeAndNil();
← →
Плохиш © (2006-10-23 13:05) [5]
> Есть интерес, почему нужно было так усложнять освобождение
Это сделано для облегчения жизни ленивых начанающих, которые ни думать, ни читать не умеют, а бегут сюда по любому чиху. Хотя эта функция своё предназначение не выполнила.
← →
Сатир (2006-10-23 13:06) [6]упс, не обратил внимание на название модуля.
оказывается, это реализовано в модуле SysUtils))))))
← →
umbra © (2006-10-23 13:06) [7]
> Может мой вариант не будет выдавать такой же результат,
> как и предыдущий?
>
вариант чего?
← →
Сатир (2006-10-23 13:15) [8]забей. вопрос исчерпан.
← →
Anatoly Podgoretsky © (2006-10-23 13:27) [9]
> Это сделано для облегчения жизни ленивых начанающих, которые
> ни думать, ни читать не умеют, а бегут сюда по любому чиху.
> Хотя эта функция своё предназначение не выполнила.
Не для этого сделано, а для тех кто не в состоянии правильно написать, это явное повторное использование переменных.
Я за все время программирования ни разу не использовал данную функцию, за ее ненадобностью.
← →
Rule © (2006-10-23 13:40) [10]Сатир (23.10.06 12:58)
Почему нельзя просто написать:
fImportExcelNakl.Free;
fImportExcelNakl:=nil; ?
потомучто если возникнет ошибка при вызове метода Free, то переменная будет указывать незнама на что, а в этой функции просто выскочет исключание, а переменная будет указывать на пустой указатель ...
помоему этот ответ ждал автор, а не о целесообразности использования данной функции
← →
Сатир (2006-10-23 14:21) [11]
> потомучто если возникнет ошибка при вызове метода Free,
> то переменная будет указывать незнама на что, а в этой функции
> просто выскочет исключание, а переменная будет указывать
> на пустой указатель ...
> помоему этот ответ ждал автор, а не о целесообразности использования
> данной функции
ну тогда можно написать
try
fImportExcelNakl.Free;
finally
fImportExcelNakl:=nil;
end;
:-)
← →
Rule © (2006-10-23 14:29) [12]Сатир (23.10.06 14:21) [11]
согласен можно, но почемуто авторов этой функции пугало использование исключений ... я просто объяснил смысл промежуточно переменной :-) нивкоем случае не настаиваю на оптимальности кода ю... мож борланд что-то страшное про исключения знает :-)
← →
guav © (2006-10-23 14:44) [13]> [9] Anatoly Podgoretsky © (23.10.06 13:27)
> это явное повторное использование переменных.
Почему же ? У меня например она применяестя для противоположной цели - для защиты от повторного использования переменной.
← →
RWolf © (2006-10-23 14:46) [14]
> Есть интерес, почему нужно было так усложнять освобождение
> и обнуление экземпляра формы?
По мне, так наоборот - такая конструкция упрощает освобождение. Печатать меньше.
В остальном - без разницы.
← →
guav © (2006-10-23 14:48) [15]> [11] Сатир (23.10.06 14:21)
Это не эквивалент.
Возможен случай когда деструктор класса переменной вызывает другой деструктор, а в другом деструкторе пытаются сделать Free той самой переменной. Тогда FreeAndNil не приведёт к ошибке, а код [11] приведёт.
← →
oldman © (2006-10-23 14:52) [16]
> Anatoly Podgoretsky © (23.10.06 13:27) [9]
> Я за все время программирования ни разу не использовал данную
> функцию, за ее ненадобностью.
+1!!!
← →
Anatoly Podgoretsky © (2006-10-23 15:05) [17]
> Почему же ? У меня например она применяестя для противоположной
> цели - для защиты от повторного использования переменной.
>
А мы одинаково понимаем термин? У меня сомнение :-(
← →
guav © (2006-10-23 15:14) [18]> [9] Anatoly Podgoretsky © (23.10.06 13:27)
> [16] oldman © (23.10.06 14:52)
Допустим ситуацию - у стрелки две точки, когда пользователь удаляет одну из точек, стрелка тоже должна быть удалена. Как переписать код без этой бесполезной функции:type
TArrowPoint = class;
TArrow = class;
TArrowPoint = class(TObject)
private
FOwner: TArrow;
public
property Owner: TArrow read FOwner;
constructor Create(Owner: TArrow);
destructor Destroy; override;
end;
TArrow = class(TObject)
private
FA, FB: TArrowPoint;
public
constructor Create;
destructor Destroy; override;
end;
constructor TArrowPoint.Create(Owner: TArrow);
begin
inherited Create;
FOwner := Owner;
end;
destructor TArrowPoint.Destroy;
begin
FreeAndNil(FOwner);
inherited;
end;
constructor TArrow.Create;
begin
inherited Create;
FA := TArrowPoint.Create(Self);
FB := TArrowPoint.Create(Self);
end;
destructor TArrow.Destroy;
begin
if FB.Owner = Self then
FB.Free;
if FA.Owner = Self then
FA.Free;
inherited;
end;
> [17] Anatoly Podgoretsky © (23.10.06 15:05)
> А мы одинаково понимаем термин? У меня сомнение :-(
Думаю одинаково. Я имел ввиду использование FreeAndNil заместо обычного Free чтобы при попытке повторно использовать переменную получить AV практически гарантированно.
← →
Anatoly Podgoretsky © (2006-10-23 15:18) [19]Э у тебя тут нет переменных, а члены класса, к тому же контролируемые, для них такое понятно, и без разницы что использовать, Free/FreeAndNil
Правда такие вещи возможно лучше делать с помощью списков?
← →
Сатир (2006-10-23 15:18) [20]
> использование FreeAndNil заместо обычного Free чтобы при
> попытке повторно использовать переменную получить AV практически
> гарантированно.
вообще-то обнуляют переменную для того, чтобы срабатывала конструкция
if Assigned(переменная) then ...
← →
Anatoly Podgoretsky © (2006-10-23 15:32) [21]
> чтобы срабатывала конструкция
> if Assigned(переменная) then ...
Вот это и есть чистое повторное использование, обнуление нужно, что бы не было ошибки при Free и конечно не для переменных, а членов класса, когда они создаются в конструкторе, а уничтожаются в деструкторе. Изредка в середине. Это не повторное использование в отличии отif Assigned(X) then Create
В нормальной программе, без повторного использования это выглядит такCreate
← →
guav © (2006-10-23 15:33) [22]> для них такое понятно, и без разницы что использовать, Free/FreeAndNil
Я ошбся, когда код приводил (выбирал из реального кода, упустил кое-что). Деструктор выгляди так:destructor TArrow.Destroy;
begin
if FB.Owner = Self then
begin
FB.FOwner := nil;
FB.Free;
end;
if FA.Owner = Self then
begin
FA.FOwner := nil;
FA.Free;
end;
inherited;
end;
Тогда создание стрелки и последующее удаление точки приводит к тому, что стрелка и обе точкинормально уничтожаются.procedure TForm1.Button1Click(Sender: TObject);
var Arrow: TArrow;
begin
Arrow := TArrow.Create;
Arrow.FA.Free;
end;
Замена FreeAndNil на Free недопустима - тогда будет Stack Overflow.
> Правда такие вещи возможно лучше делать с помощью списков?
Список из всегда двух элементов - стоит ли ?
← →
Anatoly Podgoretsky © (2006-10-23 15:37) [23]Ну так это кардинально меняет дело.
← →
guav © (2006-10-23 15:39) [24]Сделал поиск по генофонду.
FreeAndNil широко используется, и ладно бы всякие Indy и ActionMagagerы, FreeAndNil используется в finalization модулей classes и sysutils !
Т.к. это в finalization , речь о повторном использовании не идёт, это скорее
> [13] guav © (23.10.06 14:44)
> для защиты от повторного использования переменной.
← →
guav © (2006-10-23 15:41) [25]> [23] Anatoly Podgoretsky © (23.10.06 15:37)
Так как - оставить или заменить на что-то другое ?
← →
Anatoly Podgoretsky © (2006-10-23 15:50) [26]
> Сделал поиск по генофонду.
> FreeAndNil широко используется
Это ничего не значит. Вот goto не используется, кроме одного какого то вспомогательного модуля.
Борланд ввел эту функцию, из-за многочисленных ошибок программистов, а после того как ввел, то почему бы ни использовать. Но иногда это смешно выглядит.proc...
var
X: ...
begin
X := что
FreeAndNil(X);
end;
Как такое объяснишь? И это тоже из генофонда.
← →
Anatoly Podgoretsky © (2006-10-23 15:52) [27]
> Так как - оставить или заменить на что-то другое ?
Не знаю, анализ нужен, я глубоко не анализировал код, да и его недостаточно для анализа. Главное это не догма и если приложение спроектировано правильно и по каким то критериям, то имее право на существование. Но я в подобных случаях не ленюсь написать две явные строки.
← →
guav © (2006-10-23 16:02) [28]
> Не знаю, анализ нужен, я глубоко не анализировал код, да
> и его недостаточно для анализа.
Понятно... поведение вроде спроектированно правильно, а реализацию можно поменять если вдруг окажется что "FreeeAndNil considered harmful".
> Но я в подобных случаях не ленюсь написать две явные строки.
Не тот случай, там именно FreeAndNil нужен, реализации [0].
> Как такое объяснишь?
Привычка. Может даже хорошая.
Вот я бы Free написал, а ведь Destroy там бы хватило.
← →
Плохиш © (2006-10-23 16:07) [29]
> guav © (23.10.06 16:02) [28]
> Привычка. Может даже хорошая.
> Вот я бы Free написал, а ведь Destroy там бы хватило.
Вообще-то борланд в справке по Destroy все причины описал.
← →
Anatoly Podgoretsky © (2006-10-23 16:45) [30]
> Так как - оставить или заменить на что-то другое ?
Я обычно в этом случае делаю контролируемое свойсво, поле в приватную часть, а в свойстве написал бы setter и полностью бы скрыл всю реализацию, обеспечив при этом надежность.procedure .SetA(aValue: type);
begin
if FA = aValue then Exit;
if Assigned(FA) then FreeXXX
FA := AValue или варианты
Реализация подобного рода в генотипе полно.
Это полностью контролируемое поведение и деструктуры тоже правильно будут работать.
← →
Джо © (2006-10-23 16:48) [31]
> [30] Anatoly Podgoretsky ©
А по мне это уже преумножение сущностей. Равна переменная nil или нет — это, собственно, уже и есть флаг, зачем заводить дополнительный? Впрочем, я и сам так частенько делаю, так что камнем бросать не стану :)
← →
Джо © (2006-10-23 16:50) [32]Ну, "для важности" можно просто сделать:
function IsSomePropNil: Boolean
begin
Result := Assigned (FSomeValue: TObject)
end;
8^)
← →
Anatoly Podgoretsky © (2006-10-23 17:03) [33]if Assigned(FA) then FreeXXX
А здесь проверка на то, надо ли освобождать или можно сразу создавать, сам процесс скрыт от пользователя и не позволяет обойти его, путем прямого обращения к FA
И это не переменная, хотя, как я уже говорил, посмотрел бы в сторону списков, но для этого надо изучать проект, может какие ни будь динамические структуры будут лучше в данном случае.
← →
guav © (2006-10-23 19:05) [34]> [29] Плохиш © (23.10.06 16:07)
> > Вот я бы Free написал, а ведь Destroy там бы хватило.
>
> Вообще-то борланд в справке по Destroy все причины описал.
Там описана только одна причина и та про применение Free в деструкторах, в коде [26] хватило бы Destroy; .
> [30] Anatoly Podgoretsky © (23.10.06 16:45)
Это понятно, для GDIшных хендлов такое повсеместно применяется.
Но это мне не очень подходит для данного случая (деструктор там вызывается для предка, не факт что там подвернётся именно TArrowPoint).
И я стараюсь не применять без необходимости writeable class properties, т.к. при их записи нужно смотреть реализацию, там возможны варианты.
← →
Loginov Dmitry © (2006-10-24 00:24) [35]Сатир (23.10.06 12:58)
Почему нельзя просто написать:
fImportExcelNakl.Free;
fImportExcelNakl:=nil;
Этот код может оказаться потоко-небезопасным. Допустим, один объект используется в нескольких потоках. В первом потоке делаем fImportExcelNakl.Free; Далее управление может получить второй поток, код которого if Assigned(fImportExcelNakl) then <Работа с этим объектом>. AV обеспечено. Выручает процедура FreeAndNil(), которая обнуляет прежде всего ссылку, а уж после уничтожает сам объект.
← →
Petr V.Abramov (2006-10-24 00:44) [36]> Anatoly Podgoretsky © (23.10.06 15:50) [26]
> FreeAndNil(X);
> end;
> Как такое объяснишь? И это тоже из генофонда.
так полковник Кольт тоже сделал свое изобретение, чтоб уравнять людей в правах. говорять, на его могиле так и наЧЕРТАНО :) ну и? идиоты плодятся быстрее, ибо не думают об образовании детей....
← →
ИА (2006-10-24 00:49) [37]
> Не знаю, анализ нужен, я глубоко не анализировал код, да
> и его недостаточно для анализа. Главное это не догма и если
> приложение спроектировано правильно и по каким то критериям,
> то имее право на существование. Но я в подобных случаях
> не ленюсь написать две явные строки.
Я рекомендую FreeAndNil() как в данном случае, так и вообще как подход к написанию кода. Во первых, имя функции "говорящее", хорошо читается. Во-вторых, короче без ущерба понятности. И в третьих, главное, зачастую вызывают только Free() если переменная одноразовая, что тоже понятно - зачем писать лишний ненужный код, что в последствии может сыграть дурную шутку - коду свойственно меняться и чем меньше надо помнить что требуется подправлять (добавить := nil; если переменная теперь будет использоваться неоднократно, а такие изменения не редки) тем лучше и безопаснее.
← →
ИА (2006-10-24 00:50) [38]
> proc...
> var
> X: ...
> begin
> X := что
> FreeAndNil(X);
> end;
>
> Как такое объяснишь? И это тоже из генофонда.
не согласен. Смотрите выше...
← →
Anatoly Podgoretsky © (2006-10-24 01:27) [39]И в четвертых, передается нетипизированый указатель, чем полностью убивается, как рантайм, так и дизайн тайм проверка :-(
А оно надо мне такое?
← →
Германн © (2006-10-24 02:02) [40]Не пользовал FreeAndNil никогда, не пользую сейчас и очень сомнительно, что буду пользовать когда-нибудь. Разве что под страхом смертной казни. :-)
Меня в моём детском саду не обучили этой процедуре. Её тогда просто не существовало. Привык ходить сам, без этого костыля. А привычка - вторая натура. :-)
Страницы: 1 2 вся ветка
Текущий архив: 2006.11.12;
Скачать: CL | DM;
Память: 0.56 MB
Время: 0.04 c