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

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.045 c
15-1161709579
Геймер
2006-10-24 21:06
2006.11.12
Эмулятор Dos


1-1159444991
DVM
2006-09-28 16:03
2006.11.12
У TEdit какие то проблемы с маленькой буквой "я"?


15-1161759470
Курдль
2006-10-25 10:57
2006.11.12
Какие именно задачи следует решать с помощью ХП?


15-1161954746
Гарри Поттер
2006-10-27 17:12
2006.11.12
грядет сухой закон?


15-1161436618
Альберт
2006-10-21 17:16
2006.11.12
Adobe Flash...





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский