Текущий архив: 2004.08.01;
Скачать: CL | DM;
ВнизОператор IS небезопасен для форм Найти похожие ветки
← →
KSergey © (2004-07-14 15:10) [80]> Cobalt © (14.07.04 13:02)
По-моему, очень хороший пост.
И на мой взгляд, в хелпе это не написано. Хотя и не буду настаивать, не очень силен.
← →
Тимохов © (2004-07-14 15:16) [81]
> Очень интересно что ты скажешь. Так сказать, хотелось бы
> услышать комментарий :)
согласится Григорьевым Антоном я поспешил.
Я проложаю утверждать, что поведение is соответствует его цели.
для реализации поведения Антона есть inheritsfrom.
Хотя согласен, что они могли бы это реализовать и по-другому. Это не наше дело - такой компилятор. Но частной цели для которой разработан и документирован is все соответствует на 100 процентов.
>
> ну ладно, намекали :)
определенно параноик :))))
> так вот почему в памяти D7 и D6 ничего не меняется, а в
> D5 меняется.
потому, что так сложились обстоятельства.
прими как аксиому.
ЗЫ. Знаешь, чтобы копать в этой области вот тебе списко тем, после изучения которых ты можешь делать НЕумозрительные заключения:
1. Арихтектура виртуальной памяти windows.
2. обработка структурных исключений (в частности откуда и когда берется av)
3. менеджер памяти дельфи (статья Мистика есть на королевстве).
4. как создается объект (tobject.newinstance)
5. как и где хранятся такой повседневный тип как ansistring.
Вот после этого сможешь делать предположения и вообще НЕ принимать мою аксиому. Разработай свою (в точности равную моей) Но! До нее ты допрешь сам.
:)))))
← →
Sergey Kamininski (2004-07-14 15:19) [82]2 Piter © (14.07.04 13:36) [69]
НЕ смущает! Потому что ты указал ссылку НЕ на экземпляр класса, а на ЧЕРТ ЗНАЕТ ЧТО! Получил AV в программе! Задумался, оттрасировал программу, нашел ошибку, понял, исправил!
:) А ты указал ссылку не на экземпляр класса TButton, а на ЧЕРТ ЗНАЕТ ЧТО, приведенное к типу TButton. А потом пытаешься выяснить у компилятора, чтобы он таки четко тебе сказал, что это: баттон или мусор в памяти (а как он, интересно об этом догадается) или нечто, приведенное к типу баттона?
См. также: DiamondShark © (14.07.04 14:09) [75] <-- regards:)
← →
Тимохов © (2004-07-14 15:24) [83]Piter.
Повторюсь, что про compiler magic команды is я знал. Т.е. не ты мне это открыл.
Но!!! Тебя не удивляет, что тема странности is вообще (имхо) ни разу не возникала?
Меня не удивляет - у is есть определенное назначение, которое, согласен, не вполне удачно описано в документации. Но все же - ни у кого вопросов это не вызывает, т.к. все понимают о чем речь - пользуйся так как пользуется этим, например, сам борланд в vcl и проблем не будет.
Т.е. мое имхо такое - тебе сложно вынести, что ты неверно понимал is и поэтому ты ищешь причины. В частности причины найдены в доке - действительно описание дурацкое. Но это ничего не изменит - как пользовались все is для того, для чего он был разработан (но, повторюсь, плохо задокументирован) так и будут пользоваться :))))))
← →
Тимохов © (2004-07-14 15:26) [84]
> Sergey Kamininski (14.07.04 15:19) [82]
я тут прочел описание is (d6) и понял, что нельзя не согласится с piteroм в том, что описание не соответсвует семантике. Что я по этому поводу думаю я написал в предыдущих двух ответах.
Автору
Согласен с Антоном Григорьевым - пиши на статью.
ЗЫ.
Нужна ли, правда, она будет кому-то - не знаю :)) Но для общего образования полезна.
← →
Sergey Kamininski (2004-07-14 15:50) [85]2 Тимохов © (14.07.04 15:26) [84]
Ну, несоответствует, так сказать, частично ;)
If the declared type of object is unrelated to class—that is, if the types are distinct and one is not an ancestor of the other— a compilation error results.
Но намекают ведь, чтобы не баловались и не подсовывали операнду ерунду всякую ;-)
← →
Тимохов © (2004-07-14 15:52) [86]
> Sergey Kamininski (14.07.04 15:50) [85]
не здесь не соответствует - в самом начале
The is operator, which performs dynamic type checking, is used to verify the actual runtime class of an object.
вот здесь.
← →
Sandman25 © (2004-07-14 15:54) [87]P: Pointer;
type
TR1 = record
a: integer;
end;
TR2 = record
a: byte
end;
var
R1: TR1;
P := @R1;
if P is TR1 then
...
if P is TR2 then
...
Конечно, даже не откомпилируется. Но, возможно, поможет автору понять, почему реализовать is так, как он этого хочет, не получится.
И, кстати, можно написать такой пример, чтобы даже InheritsFrom вернула неверный результат. Для этого нужно досконально изучить, как хранятся TObject, создать соответсвующие структуры, чтобы при том алгоритме, с помощью которого происходят вызовы методов, произошла передача управления по нужному адресу. А по этому адресу можно записать машинный код (типа DB из ассемблера). Только, наверное, надо будет еще установить нужные флаги у страниц памяти.
← →
DiamondShark © (2004-07-14 16:03) [88]
> Тимохов © (14.07.04 15:52) [86]
А в чём несоответсвие? Или неочевидность.
Вообще, в чём недостаток описания?
← →
Sergey Kamininski (2004-07-14 16:04) [89]Сторонникам автора ветки
Милые, родные, хорошие! А как же вы предлагаете реагировать компилятору на подобный кусок, а?
procedure TForm1.Button1Click(Sender: TObject);
var
btn : TButton;
begin
btn := Pointer(TEdit.Create(nil));
if btn is TButton then
TButton(btn).Parent := self;
end;
Ну что здесь можно предложить, кроме существующей реализации оператора? Что вы, в самом деле?..
Как можно всерьез об этом говорить?
← →
Тимохов © (2004-07-14 16:05) [90]
> DiamondShark © (14.07.04 16:03) [88]
в двух словах dynamic и runtime.
дело в том, что в рельаности runtime в некторых случаях = compiletime.
← →
Тимохов © (2004-07-14 16:06) [91]Я не сторонник автора во всем, я сторонник некторых моментов, которые он заметил.
> Ну что здесь можно предложитб
например вызов inheritsfrom(TButton)
← →
KSergey © (2004-07-14 16:08) [92]> [89] Sergey Kamininski (14.07.04 16:04)
> Ну что здесь можно предложить, кроме существующей реализации
> оператора?
Взять и честно проверить ВСЕГДА что же там на самом деле. Так, как это делается в случае, скажем, когда было бы написано
if TObject(btn) is TButton then
Неужели это невозможно?? Если да, по почему???
← →
Тимохов © (2004-07-14 16:09) [93]
> Неужели это невозможно?? Если да, по почему???
считаю, что это вполне возможно.
НО! Считаю, что это сделано правильно - не правильно описана дока.
← →
STYLE © (2004-07-14 16:10) [94]
> Неужели это невозможно?? Если да, по почему???
Да потому что смысла нет в такой проверке :)
← →
DiamondShark © (2004-07-14 16:12) [95]
> Тимохов © (14.07.04 16:05) [90]
Да ну?!
← →
Тимохов © (2004-07-14 16:13) [96]
> DiamondShark © (14.07.04 16:12) [95]
>
> > Тимохов © (14.07.04 16:05) [90]
>
> Да ну?!
у нас так разговор не выйдет.
я привел конкретное возражение про хелп, вы "да ну?"
что-то хотите сказать? :))
← →
DiamondShark © (2004-07-14 16:15) [97]
> Тимохов © (14.07.04 16:13) [96]
В каких случаях проверка выполняется при компиляции?
← →
Sergey Kamininski (2004-07-14 16:17) [98]Да, дока-таки да, способна ввести в заблуждение. Видимо, парни из Борланда не смогли предусмотреть, что is кто-то всерьез будет использовать подобным образом.
← →
Тимохов © (2004-07-14 16:17) [99]
> DiamondShark © (14.07.04 16:15) [97]
>
> > Тимохов © (14.07.04 16:13) [96]
>
> В каких случаях проверка выполняется при компиляции?
Вы с луны, того, свалились? Весь топик говорится об этом :)))))
пот напримерvar
a: TMyClass;
begin
a := pointer(any integer value <> 0);
if a is TMyClass всегда будет бедет true
end;
← →
Тимохов © (2004-07-14 16:19) [100]Если никто не против выскажу очередное свое резюме
Piter докопался до того, что описании is не соответсвует ее семантике (функциональности).
Кто против?
← →
DiamondShark © (2004-07-14 16:26) [101]
> Тимохов © (14.07.04 16:17) [99]
А в CPU посмотреть?
← →
Тимохов © (2004-07-14 16:27) [102]
> А в CPU посмотреть?
посмотрите...
← →
DiamondShark © (2004-07-14 16:29) [103]
> Тимохов © (14.07.04 16:19) [100]
> Кто против?
Я.
Могу переформулировать резюме:
Иногда интуитивные предположения могут не соответсвовать криво понимаемому описанию.
← →
Тимохов © (2004-07-14 16:30) [104]Вот в таком коде
type
TMyClass = class b: integer end;
procedure TForm1.Button4Click(Sender: TObject);
var
a: TMyClass;
begin
a := pointer(2134242);
if a is TMyClass then
showmessage("hi");
end;
строчкаif a is TMyClass then
равна0045468B 837DF800 cmp dword ptr [ebp-$08],$00
0045468F 740A jz +$0a
Т.е. просто проверка <> nil.
← →
Piter © (2004-07-14 16:30) [105]Cobalt © (14.07.04 14:37) [76]
Ты согласен, что Cobalt © (14.07.04 13:02) [67] - вполне разумные ограничения?
я согласен с твоим постом... но о каких ограничениях ты говоришь? Ты просто описал поведение компилятора Дельфи :)
И тут я не согласен с этим:
var1 is It"sClassTypeOrOneOfParentClassType,
то IsClass не вызывается - просто проверяется, assigned ли эта переменная
я тут считаю (хотя писал это уже 100 раз), что IsClass вызываться должен.
Если присваивать переменной фигню типа Pointer(bla-bla-bla) - это уже твоя головная боль - делай общего предка, и баста! (если хочешь нормально работать, а не воевать с классами)
не согласен насчет баста. То есть, согласен, конечно, нужно делать правильно. Но это не исключает вопроса почему IS ведет себя таким образом. Ведь приведения типа Pointer(bla-bla-bla) в Дельфи возможны. А если они возможны, то и IS должен это учитывать. Да, в каком-то смысле это защита от дурака. Но почему бы ее не сделать?
DiamondShark © (14.07.04 14:09) [75]
А теперь внимание, вопрос. Каким образом определить, сослался ли указатель на структуру RTTI, просто на какой-то кусок памяти, или вообще за пределы адресного пространства?
Ответ: никаким.
А вот это хороший вопрос. И ответ, имхо, неправильный.
Нужно просто вызвать IsClass :)
Если он вернет True - значит, это как раз структура RTTI. Если он вызывал AV - то значит нет.
Возможны, конечно, случаи, что в памяти будут случайные наборы байтов, которые в сумме образуют нужный код, который вернет true.... но это грубо говоря маловероятно :)
или вообще за пределы адресного пространства?
а вот это интересно. Как можно сослаться за пределы адресного пространства? Вроде как адреснео пространство 4 гигабайта. И указатель это четырехбайтовое целое, которые как раз может указывать в любом диапазоне от 0 до 4-х гигабайт. Как он может указывать за адресное пространство?
← →
Тимохов © (2004-07-14 16:30) [106]Иногда интуитивные предположения могут не соответсвовать криво написанному описанию.
← →
Тимохов © (2004-07-14 16:32) [107]
> Piter © (14.07.04 16:30) [105]
Не упосртвуйте, в том, что реализация здесь должна быть иная.
Вы нашли недочет в доке - не более.
Дело за малым - убедиль алмазную укулу :))))
← →
DiamondShark © (2004-07-14 16:34) [108]
> Тимохов © (14.07.04 16:27) [102]
>
> > А в CPU посмотреть?
>
> посмотрите...
А вы испытаете мазохистское удовольствие от тыканья вас носом?
Тоды ой. Смотрите:z := pointer(123);
mov EAX, $0000007b
if z is zzz then ShowMessage("dfff");
test EAX, EAX
jz XXX
mov EAX, XXXXXXXX
call ShowMessage
<-- адрес XXX здесь
...
← →
Тимохов © (2004-07-14 16:37) [109]
> DiamondShark © (14.07.04 16:34) [108]
ой а, что это? мне умные дяди говорили, что оссеблер. Да?
у... как круто...
----------
В чем проблема? Вы видите в своем коде вызов IsClass иши InheritsFrom. Имеено об этом я и говорю: в докуме есть слово runtime, вы же наглядно показали, что никаких runtime проверок нет - все проуверки (т.е. вызов isclass или inheritsfrom) убраны еще в comilertime.
Есть предложение. Опишите строчек пять, во что вы меня хотите тыкнуть - есть ощущение, что мы говорим о разных вещах.
← →
Anatoly Podgoretsky © (2004-07-14 16:39) [110]Вообще то адресное пространство для x86 равно 2^48, Микрософт на данный момент поддерживает 64 гб
← →
Sergey Kamininski (2004-07-14 16:39) [111]Черт, а забавный вообще-то код компилируется из такого:
var
btn: TButton;
begin
btn := Pointer(TEdit.Create(nil));
if btn is TButton then
begin
TButton(btn).Parent := self;
Btn.Caption := "111";
Btn.Cancel := True;
end;
end;
Это ж надо так компилятор затуркать. На самом деле интересно выходит.
Любопытствующие могут наблюдать, какBtn.Caption := "111";
транслируются в вызовTControl.SetText
, с соответствующим результатом,а также предлагаю разобраться, куда пишется $01 вместоBtn.Cancel := True
.
Забавно.
← →
Anatoly Podgoretsky © (2004-07-14 16:39) [112]Anatoly Podgoretsky © (14.07.04 16:39) [110]
Поправка 2^46
← →
Тимохов © (2004-07-14 16:39) [113]прикольно - обсуждение разделилось на 3 лагеря.
1. is работате верно - DimondShark
2. is работает верно, но неверно сделана дока - я
3. is работает неверно - piter.
:))))
← →
DiamondShark © (2004-07-14 16:45) [114]
> Тимохов © (14.07.04 16:37) [109]
А вы видите в доке обязательство вызвать IsClass?
А вот я вижу проверку на nil.
В полном соответсвии с докой.
← →
Sergey Kamininski (2004-07-14 16:46) [115]4. В доке есть уточняющая оговорка. Впрочем, не слишком убедительная. Я. :-)
← →
Тимохов © (2004-07-14 16:48) [116]
> DiamondShark © (14.07.04 16:45) [114]
>
> > Тимохов © (14.07.04 16:37) [109]
>
> А вы видите в доке обязательство вызвать IsClass?
> А вот я вижу проверку на nil.
> В полном соответсвии с докой.
меня смущает слово runtime. согласитесь, что от такого описания ждешь другой семантики.
Хотя повторюсь, я не считаю семантику неверной - она удовлетворяет задачам на 100 процентов.
← →
ИдиотЪ (2004-07-14 16:50) [117]мне тоже кажется, что оператор
btn := Pointer(TEdit.Create(nil))
является некорректным и даже опасным, соответственно расплата может быть незамедлительно или позже. Тем более нигде не учат такому, а превращать Дельфи в жесткую систему контроля - параноя! А если начать изменять в любом месте с помощью указателей данные и чтоб Дельфи это потом отследила некорректность, на что это будет похоже?
Попробуйте для разнообразия такое:
if TButton(Edit) is TButton then
ShowMessage("Неуж-то кнопка?");
← →
nikkie © (2004-07-14 16:51) [118]>Тимохов
>Дело за малым - убедиль алмазную укулу :))))
ты чересчур оптимистичен. :))
← →
Григорьев Антон © (2004-07-14 16:51) [119]
> Piter © (14.07.04 13:36) [69]
> Sergey Kaminski (14.07.04 6:32) [43]
> Не смущает, что в таком случае AV будет всегда? Независимо
> "от версии Делфи". И количества итераций
>
> НЕ смущает! Потому что ты указал ссылку НЕ на экземпляр
> класса, а на ЧЕРТ ЗНАЕТ ЧТО! Получил AV в программе! Задумался,
> оттрасировал программу, нашел ошибку, понял, исправил!
>
> А вот тебя не смущает, что "ЛОГИЧНЫЙ" Is вернет TRUE в этом
> случае? Не кажется, что логика программы может пойти неправильным
> путем? Ибо указатель на хрен знает что признается указателем
> на TButton?
Если указатель указывает непонятно на что, то результат любых операций над ним непредсказуем. Это следует из внутреннего представления указателя в Delphi. Можно было бы выбрать другое внутреннее представление, защищающее от таких ошибок, но это привело бы к уменьшению гибкости и быстродействия. Та форма представления указателя, которая выбрана в Delphi, обеспечивает максимальную скорость и гибкость, но взамен требует от программиста, чтобы он сам следил за корректностью указателей. Если тебя интересует эта тема, могу порекомендовать пару книжек (печатных; электронных не знаю), в которых обзорно рассмотрены разные подходы к конструированию и реализации языков программирования. Оттуда, в частности, можно узнать, что указатель может быть не похож на то, что мы привыкли называть указателем.
И советую подумать над такой проблемой: как можно в принципе реализовать то, чтобы после Free is или любое другое действие гарантированно бы приводило к AV. Без твоих конкретных предложений по реализации считаю дальнейший разговор на эту тему бессмысленным.
> Тимохов © (14.07.04 15:16) [81]
> для реализации поведения Антона есть inheritsfrom.
Моё поведение ни от каких inheritsfrom не зависит!!! Я обладаю свободой воли!!! :)))
> Тимохов © (14.07.04 16:19) [100]
> Если никто не против выскажу очередное свое резюме
>
> Piter докопался до того, что описании is не соответсвует
> ее семантике (функциональности).
>
> Кто против?
Согласен. И, более того, считаю вредным выяснять, то ли поведение правильное, а описание нет, то ли, наоборот, описание правильное, а поведение - нет. Не соответсвует - и всё тут. Без дальнейших комментариев.
← →
DiamondShark © (2004-07-14 16:53) [120]
> Piter © (14.07.04 16:30) [105]
> DiamondShark © (14.07.04 14:09) [75]
> А теперь внимание, вопрос. Каким образом определить, сослался
> ли указатель на структуру RTTI, просто на какой-то кусок
> памяти, или вообще за пределы адресного пространства?
> Ответ: никаким.
>
> А вот это хороший вопрос. И ответ, имхо, неправильный.
>
> Нужно просто вызвать IsClass :)
> Если он вернет True - значит, это как раз структура RTTI.
> Если он вызывал AV - то значит нет.
>
> Возможны, конечно, случаи, что в памяти будут случайные
> наборы байтов, которые в сумме образуют нужный код, который
> вернет true.... но это грубо говоря маловероятно :)
Не надо грубо говорить, обычно от этого фигня получается.
Ты предлагаешь реализовать оператор в расчёте на то, что авось куда-то попадём? Ню-ню...
А потом подумай. Большая часть динамической памяти -- это как раз действительные экземпляры и обрывки экземпляров объектов.
И как тут твоё "маловероятно"?
> или вообще за пределы адресного пространства?
>
> а вот это интересно. Как можно сослаться за пределы адресного
> пространства? Вроде как адреснео пространство 4 гигабайта.
> И указатель это четырехбайтовое целое, которые как раз может
> указывать в любом диапазоне от 0 до 4-х гигабайт. Как он
> может указывать за адресное пространство?
Уймись, ламерок.
За одно твоё предложение тыкать куда попало по мусорному указателю тебя надо подвергать эвтаназии.
Страницы: 1 2 3 4 вся ветка
Текущий архив: 2004.08.01;
Скачать: CL | DM;
Память: 0.72 MB
Время: 0.043 c