powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Улучшил FreeAndNil. Можете не благодарить.
25 сообщений из 226, страница 9 из 10
Улучшил FreeAndNil. Можете не благодарить.
    #39955487
bk0010
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GunSmoker
Это примерно как если бы вы работали с "лапшой на GOTO" и написали "Доводы против оператора GOTO". Просто когда другие читают такие опусы, они не вполне понимают, про что говорит автор, потому что никогда не видели подобного кода - ну и понимают сказанное слишком буквально ("удалите вообще это из языка").
Это была попытка ударить по старым программистам, которые благодаря наличию goto, могли писать на Фортране, используя почти любой язык программирования, чем бесили продвинутую молодежь, которая должна была использовать или развивать их проекты. Там были еще приколы, типа использования массива из нескольких элементов вместо record с таким же количеством полей, имитация common-блоков и т.д. Удар пришелся в пустоту: новые языки появились слишком поздно.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955495
bk0010,

Ну goto это while и for и всё остальное.

А рекорды это и есть массивы, после компиляции не найдёшь отличий.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955497
bk0010
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
bk0010,

Ну goto это while и for и всё остальное.

А рекорды это и есть массивы, после компиляции не найдёшь отличий.
Ага, все так. А у любителей PL/1 была еще фишка с absolute (смысл тот же, что и в Паскале, но применялась гораздо чаще).
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955500
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitry Arefiev
Вообще у всего есть семантика и контракт. Кому это не важно, для того эти три варианта одинаковы. Кому важно, заботится о читаемости и логичности кода, для того эти три варианта существенно разные.

Если это важно, никто не мешает делать
Код: pascal
1.
2.
3.
var
  Destroy: procedure(var AObj) = FreeAndNil;
  Free: procedure(var AObj) = FreeAndNil;


Можно даже до D F N сократить, а то кто-то ещё аргумент приводит "Free печатать быстрее".

P.S. Я, может, сильно необъективно смотрю, у меня проф предпосылки: как техподдержке трейсера исключений - часто приходится отлаживать за клиента. Просто иногда действительно прямо уе**ть хочется тому, кто FreeAndNil не поставил.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955501
GunSmoker,

Классы падают хаотично ?
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955502
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема, которая находится за секунды, если бы кто-то сильно умный использовал бы FreeAndNil, превращается в многочасовой марафон за багами.

P.S. Также ещё пару раз встречал ситуацию, когда надо дополнить сторонний код, но это сделать невозможно, потому что, опять же, не обнулили поля объекта. Приходится городить монстров по проверке валидности указателя. Хотя тут, конечно, не так однозначно, ибо всегда можно сказать, что подобное расширение автором кода не предусматривалось.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955506
Даже в таком маленьком проекте 3D движка, сделали обнуление полей

https://github.com/seriva/GenesisDevice-2010/blob/63c93cf169a85f5327d36b5e4497811edb60544c/Source/Engine/General/Base.pas#L112


...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955554
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GunSmoker
Хотя тут, конечно, не так однозначно, ибо всегда можно сказать, что подобное расширение автором кода не предусматривалось.

Это как раз про то, что я выше назвал "хороший вопрос для собеседования". Более-менее опытный программист знает, что удачный проект живёт своей жизнью и за исключением отдельных узких стабильных случаев "предусматривать" его развитие скорее вредно - всё равно оно пойдёт существенно не так. Если разумная доработка требует несоразмерно больших затрат из-за того, что "автором не предусматривалось" - значит, код плохой.

С Destroy это связано следующим образом. Если соискатель говорит "использую Destroy, потому что здесь никогда не будет nil", следует выяснить, насколько это "никогда" выдержит проверку будущими непредсказуемыми доработками. И если где-нибудь прозвучит "Ну программист же должен был проверить все места, где используется объект, и увидеть, что теперь надо заменить Destroy на Free" - выше мида ему точно делать нечего.

GunSmoker
Я, может, сильно необъективно смотрю, у меня проф предпосылки: как техподдержке трейсера исключений - часто приходится отлаживать за клиента. Просто иногда действительно прямо уе**ть хочется тому, кто FreeAndNil не поставил

Почему же необъективно? Наоборот. Помнится, единственным минусом FreeAndNil называли её потенциальную опасность при вызове с левыми аргументами. Вот и скажите, кого Вам больше хочется воспитать: "тех, кто не поставил FreeAndNil и создал проблему" или "тех, кто поставил FreeAndNil и создал проблему".
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955559
Фотография Sergey1979
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А почему бы в Destroy или Free не вставить об'nil'ение объекта?
Я понимаю, что это как будто отпилили сук, на котором сидели... но "магия компилятора" и всё такое...
Ведь если уничтожить объект не занилив его - можно тоже получить потом в лоб.
Я про то, чтобы при компелиции это было так по умолчанию.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955560
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergey1979
А почему бы в Destroy или Free не вставить об'nil'ение объекта?
Я понимаю, что это как будто отпилили сук, на котором сидели... но "магия компилятора" и всё такое...

Вставьте. Возьмите тот же Free Pascal с открытыми исходниками и добавьте в него такую функциональность. И когда она заработает, причём во всех режимах, включая, например,

Код: pascal
1.
2.
3.
begin
  TObject(nil).Free;
end;



задайтесь вопросом: а нафига было так делать то, что куда лучше и без всякой магии решается одной за две минуты написанной процедурой?
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955561
Фотография Sergey1979
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Но ведь Free проверяет объект на nil.
Если я ничего не путаю.
Да, с запретом - я немного не так выразил свою мысль.
Хорошо. Я Вас понял и вопросов больше нет.
Написать где нужно FreeAndNil не проблема...
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955563
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sergey1979,

запретите.

Сугубо ради любопытства и пополнения статистики хотелось бы спросить - какое у Вас образование?
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955570
Фотография Sergey1979
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И всё-таки Вы написали глупость - СЕЙЧАС, по ряду причин, уже НЕЛЬЗЯ менять поведение по-умолчанию.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955580
softwarer
Помнится, единственным минусом FreeAndNil называли её потенциальную опасность при вызове с левыми аргументами.


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
function GetObjectClass(APointer: Pointer): TClass;
{$IFDEF MSWINDOWS}
var
  LMemInfo: TMemoryBasicInformation;

  { Checks whether the given address is a valid address for a VMT entry. }
  function IsValidVMTAddress(APAddress: Pointer): Boolean;
  begin
    { Do some basic pointer checks: Must be dword aligned and beyond 64K }
    if (UIntPtr(APAddress) > 65535) and (UIntPtr(APAddress) and 3 = 0) then
    begin
      { Do we need to recheck the virtual memory? }
      if (UIntPtr(LMemInfo.BaseAddress) > UIntPtr(APAddress)) or ((UIntPtr(LMemInfo.BaseAddress) + NativeUInt(LMemInfo.RegionSize)) < (UIntPtr(APAddress) + SizeOf(Pointer))) then
      begin
        { Get the VM status for the pointer }
        LMemInfo.RegionSize := 0;
        VirtualQuery(APAddress, LMemInfo, SizeOf(LMemInfo));
      end;
      { Check the readability of the memory address }
      Result := (NativeUInt(LMemInfo.RegionSize) >= SizeOf(Pointer)) and (LMemInfo.State = MEM_COMMIT) and
        (LMemInfo.Protect and (PAGE_READONLY or PAGE_READWRITE or PAGE_EXECUTE or PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY) <> 0) and (LMemInfo.Protect and PAGE_GUARD = 0);
    end
    else
      Result := False;
  end;

{ Returns true if AClassPointer points to a class VMT }
  function InternalIsValidClass(AClassPointer: Pointer; ADepth: Integer = 0): Boolean;
  var
    LParentClassSelfPointer: PPointer;
  begin
    { Check that the self pointer as well as parent class self pointer addresses
      are valid }
    if (ADepth < 1000) and IsValidVMTAddress(Pointer(PByte(AClassPointer) + vmtSelfPtr)) and IsValidVMTAddress(Pointer(PByte(AClassPointer) + vmtParent)) then
    begin
      { Get a pointer to the parent class' self pointer }
      LParentClassSelfPointer := PPointer(PByte(AClassPointer) + vmtParent)^;
      { Check that the self pointer as well as the parent class is valid }
      Result := (PPointer(PByte(AClassPointer) + vmtSelfPtr)^ = AClassPointer) and
        ((LParentClassSelfPointer = nil) or (IsValidVMTAddress(LParentClassSelfPointer) and InternalIsValidClass(LParentClassSelfPointer^, ADepth + 1)));
    end
    else
      Result := False;
  end;

begin
  { Get the class pointer from the (suspected) object }
  Result := TClass(PNativeUInt(APointer)^);
  { No VM info yet }
  LMemInfo.RegionSize := 0;
  { Check the block }
  if not InternalIsValidClass(Pointer(Result), 0) then
    Result := nil;
{$ELSE !MSWINDOWS}
begin
  { Not currently supported under Linux / OS X }
  Result := nil;
{$ENDIF MSWINDOWS}
end;

procedure FreeAndNil(var Obj); inline;
var
  Temp: TObject;
begin
  if GetObjectClass(Pointer(Obj)) <> nil then
  begin
    Temp := TObject(Obj);
    Pointer(Obj) := nil;
    Temp.Free;
  end;
end;



И никакой опасности что, кто - то попытается int\string\... Освободить
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955581
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный, в этом коде на каждое освобождение объекта - минимум один вызов в ядро, а то и больше. Вызов ядра - это очень медленно. Такой код просто так применять нельзя. Гораздо лучше - как в начале топика.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955596
GunSmoker,

Мы же не собираемся 1000 раз вызывать в секунду. Нормально! И безопасно!
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955597
GunSmoker,

Кстати, было бы не плохо, что бы хранились созданные объекты в каком нибудь списке. Что бы имелась возможность просмотреть и проверить на данный момент, валидные адреса
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955599
Michael Longneck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Такой список рискует стать очень узким местом
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955601
Фотография Maxim Rusov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
Нормально! И безопасно!

Хрень. Проверка должна быть на этапе компиляции. Этот код ничем не поможет, если он не вызовется. Например - где нибудь в редкой except части. Точно так-же гикнется в продакшене, что мы имеем и без этих хлопот.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955615
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
GunSmoker,
Кстати, было бы не плохо, что бы хранились созданные объекты в каком нибудь списке. Что бы имелась возможность просмотреть и проверить на данный момент, валидные адреса

Вот многопоточные приложения-то охренеют...
И, кстати, FastMM вроде память выделяет блоками и у них есть данные блока в начале (как у дин. массивов), можно покопаться если делать нечего.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955622
alekcvp,

Есть же threadvar и к тому же, если не использовать TList а обычный Arr[Pointer mod SizeArr] с пометкой ключа в true\false то это не так уж и медленно.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955648
Фотография Dmitry Arefiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что только на свечку не натянут ...
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955737
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный,

что бы получить vmt нужно прочитать то на что ссылается "указатель", т.е. прочитать непонятно что
И скрытие проблемы это гораздо хуже, нужно сразу ексепшн давать
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955741
kealon(Ruslan),

Причём тут VMT ? Он не нужен. При create записывается индекс в массив о том, что такой адрес создан. И при destructor обнуляется.


В PHP такие индексные массивы только в путь и используются.
...
Рейтинг: 0 / 0
Улучшил FreeAndNil. Можете не благодарить.
    #39955747
А мне вот стало интересно, а что быстрее. Массивы в PHP или массивы в Delphi.. На досуге проверю.

Разумеется с чистым общением ZendAPI без интерпретатора. Дабы знать на сколько поссосанная система в Delphi
...
Рейтинг: 0 / 0
25 сообщений из 226, страница 9 из 10
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Улучшил FreeAndNil. Можете не благодарить.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]