http://docwiki.embarcadero.com/RADStudio/XE5/en/Anonymous_Methods_in_Delphihttp://docwiki.embarcadero.com/RADStudio/XE5/en/Anonymous_Methods_in_Delphi
Для таких как Я "не читавших".
Там ЕСТЬ О ЧЁМ подумать.
Например о том - "как ресурсы захватываются" и "какое их время жизни".
И "как это связано с ARC".
Для "пищи ума" приведу простейший пример:
-- каково поведение этого кода?
P.S. Ну и ещё "пища для мозгов" - https://plus.google.com/+RomanYankovsky/posts/cvJgAAZmhw6
Для таких как Я "не читавших".
Там ЕСТЬ О ЧЁМ подумать.
Например о том - "как ресурсы захватываются" и "какое их время жизни".
И "как это связано с ARC".
Для "пищи ума" приведу простейший пример:
program Test; type X = reference to procedure; A = class protected f_Field : Integer; public procedure B; end; // A var l_X : X; procedure A.B; begin l_X := procedure (Self.f_Field := Self.f_Field + 1;); end; var l_A : A; begin l_A := A.Create; l_A.B; l_A.Free; l_X; end;
-- каково поведение этого кода?
P.S. Ну и ещё "пища для мозгов" - https://plus.google.com/+RomanYankovsky/posts/cvJgAAZmhw6
Ужасное поведение у этого кода. Во первых, он не скомпилируется.
ОтветитьУдалитьА во-вторых, при отключенном флаге контроля за использованием освобождённой памяти в FastMM он скорее всего не выдаст никакой ошибки.
Delphi вообще в некоторых случаях довольно бесстрастно проглатывает попытки использования освобождённых объектов.
"Во первых, он не скомпилируется."
УдалитьПочему это? Я ПРИЗНАЮСЬ - его не компилировал. Но он ПО-МОЕМУ не противоречит ДОКУМЕНТАЦИИ. Или ПРОТИВОРЕЧИТ? (Какому пункту?)
"А во-вторых, при отключенном флаге контроля за использованием освобождённой памяти в FastMM он скорее всего не выдаст никакой ошибки."
Вот это - НЕ ПОНЯЛ! Можно подробнее?
Не скомпилируется. Забыл begin-end в анонимной процедуре и в конце должен быть end с точкой. Но это мелочи. Главное, сам код понятен.
Удалитькак Роман верно заметил там не хватает begin и end.
ОтветитьУдалить> Вот это - НЕ ПОНЯЛ! Можно подробнее?
У меня этот код выполнился без видимых ошибок.
> А во-вторых, при отключенном флаге контроля за использованием освобождённой памяти в FastMM он скорее всего не выдаст никакой ошибки
В FastMM (полной версии) есть директива, при включении которой FastMM будет следить, чтобы никто не использовал уже освобождённую память. И в случае чего, выдавать exception.
"как Роман верно заметил там не хватает begin и end."
Удалить-- ну блин.. вы же понимаете, что "глупо к запятым цепляться". Я же "мысль" озвучил.
Как Роман написал:
"Но это мелочи. Главное, сам код понятен."
:-)
"У меня этот код выполнился без видимых ошибок."
-- ГОТОВ ПОВЕРИТЬ! :-) Но это у МЕНЯ ТОЛЬКО есть ощущение, что то что КОД ВЫПОЛНЯЕТСЯ - это БОЛЕЕ ЧЕМ СТРАННО?
Или я что-то пропустил в этой жизни?
Ну БЕЗ ARC конечно.
С ARC - ВСЁ МОГУ ПОНЯТЬ, БЕЗ ARC - не понимаю.
Ну и в свете этого поста - "у меня глаза ОТКРЫЛИСЬ" - почему Emb - так ARC ПРОДВИГАЕТ.
"как Роман верно заметил там не хватает begin и end."
Удалить;-) что сказать :-) "глаз замылился". Написал "как у меня в скриптах".
> Но это у МЕНЯ ТОЛЬКО есть ощущение, что то что КОД ВЫПОЛНЯЕТСЯ - это БОЛЕЕ ЧЕМ СТРАННО?
УдалитьВсё-равно не вижу ничего особенного. Обычный привычный для Delphi баг. Ну т.е. как. ничего странного. Конечно такой код он не должен выполняться. Конечно должна быть ошибка. И она кстати иногда и бывает. Но не всегда. Поэтому иногда имеет смысл писать Assert(assigned(Self));
Вот пример аналогичного бага использующего уже освобожденный объект без какой-либо ошибки. Проверял в Delphi 6 (с отключенной оптимизацией!).
https://gist.github.com/tdelphi/8609918
Причём, если заменить присвоение Delimiter на вызов Add - то тогда получим AV.
"Поэтому иногда имеет смысл писать Assert(assigned(Self));"
УдалитьЭто со всеобщим то "трендом отрицания FreeAnNil" ;-) Как же "Бауэр сказал, а Ходжес - подпел" :-)
"Поэтому иногда имеет смысл писать Assert(assigned(Self));"
-- был бы FreeAndNil - вопросов бы не было. И Delphi тут ВООБЩЕ непричём. Этот пример НАГЛЯДНО показывает как НЕ НАДО программировать.
"Обычный привычный для Delphi баг."
-- до Delphi7 включительно - "обычных" багов - не было. Лишь кривые руки прикладных программистов. А таким заявлением - вы меня пугаете.
Чем "мой" пример отличается от "вашего"?
УдалитьТем что за объектами программист (при желании) - может уследить. А когда появляются ссылки на анонимные методы. Да ещё и с возможностью отдачи наружу (а не только внутрь), то "уследить" становиться практически невозможно. Разве что только взять себе за правило - наружу ссылки на анонимные методы не отдавать. Только внутрь. И не хранить их нигде кроме как во входных параметрах или локальных переменных.
> Тем что за объектами программист (при желании) - может уследить. А когда появляются ссылки на анонимные методы. Да ещё и с возможностью отдачи наружу (а не только внутрь), то "уследить" становиться практически невозможно.
УдалитьПозволю себе не согласиться. Объект - это ссылка. Ссылка на анонимный метод - это тоже ссылка. И тут уже без разницы - какую из внутренних ссылок объекта программист отправил в свободное плавание за пределы области объекта. Ссылку на анонимную процедуру, или ссылку на внутренний объект. Сам отправил - сам и следи. Только надо учитывать, что Delphi может не предупредить программиста о том, что используемая им ссылка указывает на освобожденный объект.
Просто