Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.12.24;
Скачать: CL | DM;

Вниз

Вычисление булевых выражений   Найти похожие ветки 

 
pasha_golub ©   (2006-11-30 11:37) [0]

Прямо мистика какая-то. В среде включено укороченное вычесление, по умолчанию.

Имеется код:


 If Assigned(APrevFocusedNode) and APrevFocusedNode.Values[tlcCompositeModified.ItemIndex] then
...


APrevFocusedNode = nil на момент выполнения этой инструкции. По идее, не должно происходить дальнейшего вычисления. А оно происходит, и ясен пень, с вылетом на AV.

Думал какие-то настройки локальные вмешались. Прямо перед строкой этой поставил:

{$BOOLEVAL OFF}

Не помогло. Поставил {$B-}, эффект тот же самый.

Попробовал перестроить условие:

 If Assigned(APrevFocusedNode) then
 If APrevFocusedNode.Values[tlcCompositeModified.ItemIndex] then


Так работает без ошибки.

Вопрос: почему так происходит?


 
vuk ©   (2006-11-30 11:43) [1]

Попробовать можно следующие варианты:
1. Отключить оптимизацию
2. Заменить Assigned на сравнение с nil


 
pasha_golub ©   (2006-11-30 11:46) [2]


> 1. Отключить оптимизацию

Попробовал. Не помогло.

Сейчас второе...


 
pasha_golub ©   (2006-11-30 11:48) [3]

If (APrevFocusedNode <> nil) and APrevFocusedNode.Values[tlcCompositeModified.ItemIndex] then

Тоже не сработало


 
pasha_golub ©   (2006-11-30 11:52) [4]


function VarToBoolDef(const V: Variant; const ADefault: boolean): boolean;
begin
 Result := ADefault;
 if V <> Null then try
   Result := V;
 except
   Result := ADefault
 end;
end;

If (APrevFocusedNode <> nil) and VarToBoolDef(APrevFocusedNode.Values[tlcCompositeModified.ItemIndex],False) then


А вот если так, то работает.


 
umbra ©   (2006-11-30 11:56) [5]

наверное APrevFocusedNode <> nil


 
pasha_golub ©   (2006-11-30 12:00) [6]


> наверное APrevFocusedNode <> nil
>

http://www.farata.kr.ua/FTP/other/debug.png

Триста раз проверил.


 
pasha_golub ©   (2006-11-30 12:04) [7]

Я так понимаю дело в том, что:

   property Values[Index: Integer]: Variant read GetValue write SetValue;

И, наверное, происходят какие-то манипуляции с подготовкой этих вариантов. Может быть такое?


 
Юрий Зотов ©   (2006-11-30 12:04) [8]

Паш, надеюсь, после изменения опций ты делал Build (причем Build All), а не просто Compile?


 
vuk ©   (2006-11-30 12:05) [9]

А можно увидеть что конкретно сгенерил компилятор?


 
pasha_golub ©   (2006-11-30 12:10) [10]


> Юрий Зотов ©   (30.11.06 12:04) [8]
>
> Паш, надеюсь, после изменения опций ты делал Build (причем
> Build All), а не просто Compile?
>

Да, конечно.


> vuk ©   (30.11.06 12:05) [9]
>
> А можно увидеть что конкретно сгенерил компилятор?

В смысле CPU окошко? Не нашел как скопипастить, сейчас сделаю скрин.


 
vuk ©   (2006-11-30 12:12) [11]

>Не нашел как скопипастить, сейчас сделаю скрин.
Не, ну совсем обленился! :o)


 
pasha_golub ©   (2006-11-30 12:13) [12]

Окошечно ЦПУ:

http://www.farata.kr.ua/FTP/other/debug1.png (9Кб)


 
pasha_golub ©   (2006-11-30 12:14) [13]


> Не, ну совсем обленился! :o)

Думал, сначалу руками набрать, но потом подумал, что лучше исключить фактор кривизны. ;0)


 
wal ©   (2006-11-30 12:21) [14]

Вот оно, так как второе значение - вариант, то первое тоже приводится к варианту, над ними выполняется and, результат приводится boolean. Почему именно так - хз, видимо где-то какой то приоритет битовых операций над логическими.


 
vuk ©   (2006-11-30 12:23) [15]

Я может чего не понял, но по ходу пьессы, получается, что не вариант приводится к boolean, а результат первого сравнения без всякого анализа конвертируется в вариант (VarFromBool), потом принудительно при помощи VarAnd производится логическая операция со второй частью, где все и обламывается.


 
pasha_golub ©   (2006-11-30 12:24) [16]


> wal ©   (30.11.06 12:21) [14]

Действительно. Интересный факт оказывается. И налететь на него можно с размаху, и не понять в чем дело.


 
Суслик ©   (2006-11-30 12:27) [17]

А опциях всего проекта что стоит по поводу bool eval?


 
Суслик ©   (2006-11-30 12:28) [18]

Дельфи, кстати, какой?


 
wal ©   (2006-11-30 12:29) [19]


> [16] pasha_golub ©   (30.11.06 12:24)
Порылся в хелпе:
Except for comparisons, which always return a Boolean result, any operation on a variant value returns a variant result. If an expression combines variants with statically-typed values, the statically-typed values are automatically converted to variants.


 
pasha_golub ©   (2006-11-30 12:30) [20]


> Суслик ©   (30.11.06 12:27) [17]
>
> А опциях всего проекта что стоит по поводу bool eval?
>

В первом же посте писал: отключено complete boolean eval


 
pasha_golub ©   (2006-11-30 12:32) [21]


> Суслик ©   (30.11.06 12:28) [18]
>
> Дельфи, кстати, какой?
>

D7


> wal ©   (30.11.06 12:29) [19]

Thanks. Надо себе в память заложить!!!


 
Суслик ©   (2006-11-30 12:32) [22]


>  [20] pasha_golub ©   (30.11.06 12:30)

прости, не заметил :)


 
Суслик ©   (2006-11-30 12:32) [23]

Да... факт интересный.


 
vuk ©   (2006-11-30 12:33) [24]

Кстати, а что будет, если написать

If Assigned(APrevFocusedNode) and (APrevFocusedNode.Values[tlcCompositeModified.ItemIndex] = true) ?


 
pasha_golub ©   (2006-11-30 12:35) [25]


> vuk ©   (30.11.06 12:33) [24]


> If Assigned(APrevFocusedNode) and (APrevFocusedNode.Values[tlcCompositeModified.
> ItemIndex] = true)

Сработало, как и ожидалось. Но тут на лицо явное мошенничество. :)


 
vuk ©   (2006-11-30 12:39) [26]

>Но тут на лицо явное мошенничество. :)
Нет. Таким образом мы просто сделали преобразование в другом месте и  получили сравнение уже двух булевых переменных.


 
Anatoly Podgoretsky ©   (2006-11-30 12:40) [27]

> vuk  (30.11.2006 12:23:15)  [15]

Налицо полное вычисление выражения.


 
Anatoly Podgoretsky ©   (2006-11-30 12:41) [28]

> pasha_golub  (30.11.2006 12:30:20)  [20]

По приведено снимку видно, что ни о каких boolean eval говорить не приходится.


 
pasha_golub ©   (2006-11-30 12:43) [29]


> Anatoly Podgoretsky ©   (30.11.06 12:41) [28]

В первом посте сказано:


> В среде включено укороченное вычесление


Кстати, ошибку заметил. :) Вычисление...


 
Anatoly Podgoretsky ©   (2006-11-30 12:45) [30]

> pasha_golub  (30.11.2006 12:35:25)  [25]

Ну ты понял, никаких булевых вычислений нет если вторая часть вариант, а во втором случае есть, за счет простого трюка.
Но решение ты знаешь, когда не уверен в булевых вычислениях делай в два приема

if 1 then
  if 2 then

Это гарантирует и полную независимост от настроек и от подобных фокусов по замене логических выражений на операции с вариантами.


 
vuk ©   (2006-11-30 12:47) [31]

to Anatoly Podgoretsky ©   (30.11.06 12:40) [27]:
>Налицо полное вычисление выражения.
Похоже, что компилятор решил, что для вычисления выражения нужно все вычисления делать в вариантах и уже потом получать из этого boolean. А and он в данном случае мог вообще трактовать не как логический, а как побитовый. Судя по тому что он сгенерировал, так и вышло.


 
Суслик ©   (2006-11-30 12:50) [32]

Я все-таки не понял, *зачем* компилятор вычислял второе выражение?
Ну ясное дело, что variant"ы. Но полностью то вычислять зачем

Признаюсь я до конца не понял приведенную выше ссылку на доку:

Except for comparisons, which always return a Boolean result, any operation on a variant value returns a variant result. If an expression combines variants with statically-typed values, the statically-typed values are automatically converted to variants.

Ну сказано здесь, что он к вариантам приводит. Но это имеется в виду, что он код генерит, который приводит. Зачем генерить код, который вычисляет второй параметр?

Объясните пжлст.


 
wal ©   (2006-11-30 12:53) [33]


> Зачем генерить код, который вычисляет второй параметр?
Чтобы в результате and вернуть вариант, единственное исключение, когда в результате не вариант - операции сравнения.


 
Суслик ©   (2006-11-30 12:54) [34]

Я может быть тупой, но вычислять то зачем?
Вернуть можно и не вычисляя.


 
Суслик ©   (2006-11-30 12:55) [35]

Т.е. я не вижу из доки того факта, что вычисляться должны оба выражения.


 
Суслик ©   (2006-11-30 12:55) [36]

Собственно интерес простой - может это баг?
Тогда его запостить нужно в QC.


 
pasha_golub ©   (2006-11-30 13:03) [37]


> Суслик ©   (30.11.06 12:55) [36]
>
> Собственно интерес простой - может это баг?
> Тогда его запостить нужно в QC.

В принципе, я тоже склоняюсь к данному мнению.


 
wal ©   (2006-11-30 13:04) [38]


> [34] Суслик ©   (30.11.06 12:54)
Потомучто Variant(False) и False - вещи разные


 
wal ©   (2006-11-30 13:08) [39]


> [36] Суслик ©   (30.11.06 12:55)
Это поведение описано в хелпе, какой же это баг?


 
Anatoly Podgoretsky ©   (2006-11-30 13:17) [40]

> pasha_golub  (30.11.2006 12:43:29)  [29]

Включено, только ни о каких логических вычислениях и речи нет, вот пример, который ты обозвал трюком, как раз честный, идет логическое вычисление и слева и справа Boolean


 
Anatoly Podgoretsky ©   (2006-11-30 13:19) [41]

> vuk  (30.11.2006 12:47:31)  [31]

Да посчитал и он имеет на это право, поскольку справа вариант, а там может быть и не Boolean


 
Anatoly Podgoretsky ©   (2006-11-30 13:21) [42]

> Суслик  (30.11.2006 12:50:32)  [32]

А что ему делать, если выражение не логическое?
Там получается следующее

Variant(1) and Variant2

Левую половину можно преобразовать в Вариант всегда, а правую в логическое не всегда.


 
Anatoly Podgoretsky ©   (2006-11-30 13:22) [43]

> wal  (30.11.2006 13:04:38)  [38]

А еще лучше это в выглядит для True и еще лучше

Variant(False) и string


 
TUser ©   (2006-11-30 13:30) [44]

Возможно отладчик глючит. Пару раз было, вроде. Лесился приемами типа
var i: integer;
begin
 i := integer (YourPointer);
 ShowMessage (inttostr (i));

конечно, не отладчик, но замена ему.


 
wal ©   (2006-11-30 13:35) [45]


> [44] TUser ©   (30.11.06 13:30)
Да вроде разобрались уже, отладчик не причем


 
Anatoly Podgoretsky ©   (2006-11-30 13:42) [46]

> TUser  (30.11.2006 13:30:44)  [44]

Да ничего не глючит, у него нормальный указатель, CPU это доказывает и правильно написаный код тоже работает, это тот где справа Expr = True


 
Суслик ©   (2006-11-30 13:43) [47]


>  [39] wal ©   (30.11.06 13:08)
>
> > [36] Суслик ©   (30.11.06 12:55)
> Это поведение описано в хелпе, какой же это баг?

Где описано? Какое конкретное слово? А?
Описано, что преобразует, но не описано, что вычисляет полностью.


 
Суслик ©   (2006-11-30 13:51) [48]


> [39] wal ©   (30.11.06 13:08)
>
> > [36] Суслик ©   (30.11.06 12:55)
> Это поведение описано в хелпе, какой же это баг?


Может быть там еще в доке что-то есть по этому поводу? Т.к. фраза сама по себе не говорит о том, что должно быть полное вычисление.

Ты где это нашел? Какой раздел?

PS. В BDS, кстати тоже самое.


 
wal ©   (2006-11-30 14:00) [49]


> [48] Суслик ©   (30.11.06 13:51)
Ради тебя специально хелп перерыл, с тебя пиво.
Boolean operators
...
Note

If either operand involves a variant, the compiler always performs complete evaluation (even in the {$B-} state).


 
Суслик ©   (2006-11-30 14:06) [50]


>  [49] wal ©   (30.11.06 14:00)

Спасибо.
Это уже говорит о сабже!

Не знал, кстати.
Дя и вариантами не пользуюсь :)

(будешь в пятницу, будет пиво).


 
Anatoly Podgoretsky ©   (2006-11-30 14:11) [51]

> wal  (30.11.2006 14:00:49)  [49]

Можно считать данный пост последней точкой


 
wal ©   (2006-11-30 14:13) [52]


> [50] Суслик ©   (30.11.06 14:06)
> (будешь в пятницу, будет пиво).

Как-нибудь в следующий раз. На паравоз не успеваю.
Хотя мне и без этого насилия над хелпом еще из [19] стало понятно, что получаем мы Boolean(Variant(Param1) and Param2), что в данном случае and не является логической операцией, и, соответственно, short-circuit Boolean evaluation к ней неприменим.


 
pasha_golub ©   (2006-11-30 14:57) [53]


> wal ©   (30.11.06 14:00) [49]


> Note
>
> If either operand involves a variant, the compiler always
> performs complete evaluation (even in the {$B-} state).

Спасибо. Хотя я бы это назвал не Note, a Warning. :)


 
Суслик ©   (2006-11-30 15:29) [54]


> Хотя мне и без этого насилия над хелпом еще из [19] стало
> понятно, что получаем мы Boolean(Variant(Param1) and Param2),
> что в данном случае and не является логической операцией,
> и, соответственно, short-circuit Boolean evaluation к ней
> неприменим.


Какой гениальный :)
Вообще в коде

type
  o = class
     dd: string;
     function v: variant;
  end;

function o.v;
begin
  result := true;
  dd := "24123541";
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  oo: o;
begin
  oo := nil;
  if (oo <> nil) and oo.v then
  begin
     showmessage("a");
  end;
end;


Им ничего не мешало построить иной код

Unit1.pas.45: if (oo <> nil) and oo.v then

0046B6B9 8D45E4           lea eax,[ebp-$1c]
0046B6BC 837DF800         cmp dword ptr [ebp-$08],$00
0046B6C0 0F95C2           setnz dl
0046B6C3 E81899FAFF       call @VarFromBool

например тут проверить, что результат @VarFromBool равен true.
0046B6C8 8D45E4           lea eax,[ebp-$1c]
0046B6CB 50               push eax
0046B6CC 8D55D4           lea edx,[ebp-$2c]
0046B6CF 8B45F8           mov eax,[ebp-$08]
0046B6D2 E879FFFFFF       call o.v
0046B6D7 8D55D4           lea edx,[ebp-$2c]
0046B6DA 58               pop eax
0046B6DB E850B0FAFF       call @VarAnd
0046B6E0 8D45E4           lea eax,[ebp-$1c]
0046B6E3 E88873FAFF       call @VarToBool
0046B6E8 84C0             test al,al
0046B6EA 740A             jz $0046b6f6


 
Суслик ©   (2006-11-30 15:30) [55]

Топик все же очень полезный - век живи, иногда читай www.delphimaster.ru, век учись.


 
wal ©   (2006-11-30 15:49) [56]


> например тут проверить, что результат @VarFromBool равен
> true.
И что? Сразу вернуть False? and в данном контексте не булева операция, и не обязана возвращать Variant(True) или Variant(False)


 
Alx2 ©   (2006-11-30 15:58) [57]

>wal ©   (30.11.06 15:49)

А "if" разве не говорит о булевости?


 
wal ©   (2006-11-30 16:02) [58]


> [57] Alx2 ©   (30.11.06 15:58)
Вот результат потом и приводится к Boolean, а сам оператор and разве "знает", что над ним if?


 
Alx2 ©   (2006-11-30 16:09) [59]

>wal ©   (30.11.06 16:02) [58]

> а сам оператор and разве "знает", что над ним if?

Это вроде как работа компилятора. Он же "знает", что применять если if a and b then ...
и если просто a := a and b;
побитовый and и логический как-то определены в синтаксисе. А здесь, мне кажется, выглядит как исключение из правил.


 
Alx2 ©   (2006-11-30 16:12) [60]

>wal ©   (30.11.06 16:02) [58]

Хотя неоднозначность есть - что-то вроде разницы между
if (a and b) и if (a) and (b) в случае вариантов


 
Суслик ©   (2006-11-30 16:19) [61]


>  [58] wal ©   (30.11.06 16:02)
>
> > [57] Alx2 ©   (30.11.06 15:58)
> Вот результат потом и приводится к Boolean, а сам оператор
> and разве "знает", что над ним if?

И что ты так защищаешь компилятор? Это его дело - оптимизацией заниматься.
Вона - есть среды выполнения, которые перекомпилируют на лету код циклов, если на то есть необходимость.

-------

Ну ничего страшного. Примем данный факт за фичу. Не сказать, чтобы природа фичи ясна было. Но таково состояние компилитора. Их (разработчиков) право. Радует то, что данный факт указан в документации. Я уже привык, что многие тонкие моменты они в доке не любят обозначать. А тут на те - есть :)


 
wal ©   (2006-11-30 16:20) [62]


> Это вроде как работа компилятора. Он же "знает" ...
Откуда? Он только на этапе проверки (в if) или присваивания (в :=) приводит результат к нужному типу.


 
Суслик ©   (2006-11-30 16:26) [63]

Ладно, давай не спорить - все равно правды не найдем.
Я не согласен с такой семантикой. Ты, судя по всему, согласен.
Ну и ладно.

----
Они так сделали, потому что так было легче. Их можно понять. Хорошо, что задокументировали. Молодцы. Можно привыкнуть к любой странности, лишь бы была специфицирована.


 
wal ©   (2006-11-30 16:26) [64]


> [61] Суслик ©   (30.11.06 16:19)
> И что ты так защищаешь компилятор?
Да ничуть, просто разобрали конкретный пример, разобрали поведение компилятора, для себя я счел его правильным, к тому же, как выяснилось, это поведение документировано.


 
Alx2 ©   (2006-11-30 16:28) [65]

>Суслик ©   (30.11.06 16:19)

>И что ты так защищаешь компилятор?

Вовсе не защищаю.

>Это его дело - оптимизацией заниматься.

:)

>wal ©   (30.11.06 16:20) [62]

>Откуда?  Он только на этапе проверки (в if)
>или присваивания (в :=) приводит результат к нужному типу.

Да, с вариантами, кажется, получается, так.  Неприятная особенность.


 
Суслик ©   (2006-11-30 16:28) [66]


> Да ничуть, просто разобрали конкретный пример, разобрали
> поведение компилятора, для себя я счел его правильным, к
> тому же, как выяснилось, это поведение документировано.

Ну не надо :)
Ты сказал, что тебе было ясно это почти сразу. Ну я тебя гением обозвал. С этого то и началось. Хорошо - не гений.

Тут логика, со стороны разработчиков компилятора одна - так было сделать существенно проще. Почему? Не знаю. Но думаю, что это так.



Страницы: 1 2 вся ветка

Текущий архив: 2006.12.24;
Скачать: CL | DM;

Наверх




Память: 0.64 MB
Время: 0.038 c
2-1164976291
daser
2006-12-01 15:31
2006.12.24
Как можно "пройтись" в цикле по все цветам (TColor)?


2-1165410037
Дева
2006-12-06 16:00
2006.12.24
ADO+DBF


6-1153776477
decil
2006-07-25 01:27
2006.12.24
100-continue header и ISAPI приложение под WEB-Broker.


2-1165172811
Black_Shem
2006-12-03 22:06
2006.12.24
Импорт из документа word


2-1164908261
aleko
2006-11-30 20:37
2006.12.24
отображение формы