Форум: "Прочее";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];
ВнизЧудеса Найти похожие ветки
← →
Юрий Зотов © (2014-11-01 09:40) [0]Убил 2 дня на вылавливание такого глюка
Java. В одном из методов одного из классов есть такой кусок кода с тремя локальными переменными:
boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
if (var1 && var2 &&var3)
что-то делаем;
Этот код работает и прекрасно делает то, что от него нужно. Причем var1 и var2 в программе живут давно и успешно, а вот var3 появилась недавно - после чего вдруг перестал работать совершенно другой функционал, с этим кодом никак не связанный. Ошибок не выдает, но и не работает как надо.
Поскольку вместе с var3 в программу было внесено еще немало изменений, отлов плюхи был совсем неочевидным и стоил 3 дня нервов. И встретилось вот такое чудо. Комментирую кусок кода:
boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
if (var1 && var2) // Комментарий &&var3)
что-то делаем;
То есть, переменная var3 из if исключена и нигде не читается (о чем Eclipse честно предупреждает). А отвалившийся в другом месте функционал при этом вдруг восстановился!!!!
В изумлении чешу репу, но объяснить это чудо не могу. Тогда делаю фантастическое предположение, что, поскольку var3 стала ненужной, то java выкинула и ее вычисление вместе с Выражением3. Дело в том, что в Выражении3 вызываются методы, которые действительно могут повлиять на другие места программы - и если это выражение было выкинуто (хотя выкидывать вызовы функций нельзя никакому оптимизатору), то вот такое чудо и произошло.
Проверяю это фантастическое предположение следующим образом - делаю переменную var3 снова используемой:
boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
if (var1 && var2) // Комментарий &&var3)
что-то делаем;
System.out.println(var3);
Теперь Выражение3 снова вычисляется - то есть искомый функционал снова должен отвалиться. А он работает!!!
В общем, совершенно четко установлено, что если var3 участвует в if, то глюк есть, а если не участвует, то глюка нет. При этом неважно, вычисляется Выражение3, или нет.
Чудеса?
← →
Rouse_ © (2014-11-01 11:08) [1]Ха, у нас глюк был, который впрочем в последствии оказался глюком отладчика, без отладки все работало норм, так вот, представь:
Есть модуль, разрабатываемый и работающий годами, но в какой- то момент этот модуль стало нельзя комментировать, т.е. Добавляем любой коментарий в любом месте модуля и при отладке происходит крах приложения. Чудеса? :)))
← →
Dimka Maslov © (2014-11-01 11:10) [2]В дельфи то же такие глюки были. Я даже для написал процедурку
procedure Hole(var V);
asm
end;
Чтобы компилятор с оптимизатором думали, что переменная дальше где-то ещё используется и не выкидывали её.
← →
DVM © (2014-11-01 11:36) [3]
> Юрий Зотов © (01.11.14 09:40)
> Дело в том, что в Выражении3 вызываются методы, которые
> действительно могут повлиять на другие места программы
> Чудеса?
Почему же чудеса? Это косяк программиста. Функция (а ведь там функция раз она используется в выражении), которая кроме выполнения своей основной задачи (возвращения значения) меняет явно или неявно еще какие то внешние по отношению к ней переменные (в том числе поля класса) - это уже повод задуматься над ее рефакторингом.
← →
Юрий Зотов © (2014-11-01 12:14) [4]> DVM © (01.11.14 11:36) [3]
О побочных эффектах я где-то когда-то тоже слышал. Лет этак 40 назад.
:o)
Но там далеко не все так просто, как показано в примере. Дело в том, что функция, участвующая в Выражении3, может влиять на программу неявно, через сервер приложений. И избежать этого нельзя - так устроен сервер. Ну да и ладно, с этим мы уж как-нибудь разберемся.
А чудо совсем не в этом, а вот в чем.
Этот код дает глюк:boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
if (var1 && var2 && var3)
что-то делаем;
Комментируем кусок IF"а, не трогая Выражения3. Глюк вдруг исчез:boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
if (var1 && var2) // Комментарий && var3)
что-то делаем;
Предполагаем, что Выражение3 было выброшено. Делаем так, чтобы оно уж точно вычислялось. Глюка все равно нет:boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
if (var1 && var2) // Комментарий && var3)
что-то делаем;
System.out.println(var3);
Получается следующее: независимо от Выражения3 глюк возникает приif (var1 && var2 && var3)
и глюк исчезает приif (var1 && var2) // Комментарий && var3)
А вот это уже чудо. Поскольку var3 - всего лишь локальная переменная.
← →
DVM © (2014-11-01 12:46) [5]
> Юрий Зотов © (01.11.14 12:14) [4]
А в Java нет такой штуки вроде отложенных вычислений, т.е код вычисляется не сразу а по мере необходимости в нем? Т.е выражение 1 и выражение 2 вычисляются не в момент присваивания, а в момент чтения значений переменных в условии? Это могло бы объяснить странное поведение, если они зависят от выражения 3 косвенно.
← →
Inovet © (2014-11-01 14:39) [6]1. Последовательность вызовов функций в Выражение_1, Выражение_3, Выражение_3 может влиять на результат?
2. Если вместо
что-то делаем;
поставить
делаем что-то нейтральное;
← →
Ellisium © (2014-11-02 18:21) [7]Дядь Юр, в данном примере, как мне кажется, у вас порочная логика.
С одной стороны, вы намекаете, что глюк связан с вычислением переменной var3. С другой стороны, когда вы делаете вывод:
> System.out.println(var3);
то глюка по прежнему нету. Но ведь выражение вычислено, вы результат видите в консоли (или где там).
Отсюда делаем вывод, что вычисление результата var3 не влияет на глюк.
Таким образом все сводится к тому, что у вас программа глючит, а если что-то поменять в коде - то не глючит. И связи не прослеживается.
Откуда уверенность, что это глюк java - непонятно.
← →
Юрий Зотов © (2014-11-02 19:16) [8]> Ellisium © (02.11.14 18:21) [7]
> Отсюда делаем вывод, что вычисление результата var3 не влияет
> на глюк.
Я сделал такой же вывод (о чем уже говорил).
> Откуда уверенность, что это глюк java - непонятно.
Во-первых, я нигде не утверждал, что это глюк именно Джавы. Вообще, Джаву упомянул лишь в самом начале и лишь для конкретики.
Во-вторых, поскольку var1, var2 и var3 - локальные булевские переменные, вот это ошибкой программиста быть не может никак (причем на любом языке и независимо ни от чего):if (var1 && var2)
- работает без глюков.if (var1 && var2 && var3)
- работает с глюком.
PS
Просьба читать внимательнее. Очень не хочется пояснять сабж в четвертый раз.
← →
sniknik © (2014-11-02 23:28) [9]> А в Java нет такой штуки вроде отложенных вычислений
+
> 1. Последовательность вызовов функций в Выражение_1, Выражение_3, Выражение_3 может влиять на результат?
=
???
отложенное вычисление (/выкинуты оптимизатором переменные), вызов функции на месте сравнения, причем, сравнение идет с конца... т.к.boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
if (var1 && var2) // Комментарий && var3)
что-то делаем;
System.out.println(var3);
глюка нет.
если так, по логике, то -boolean var1 = Выражение_1;
boolean var2 = Выражение_2;
boolean var3 = Выражение_3;
System.out.println(var3);
if (var1 && var2) // Комментарий && var3)
должен быть глюк.
← →
Плохиш © (2014-11-03 00:14) [10]Подозреваю, что "глюк" в выполнении и не выполнении куска "
что-то делаем;
"
← →
Юрий Зотов © (2014-11-03 00:46) [11]> Плохиш © (03.11.14 00:14) [10]
"Что-то делаем" - это заведомо существующий объект добавляется в заведомо существующий список. Проверено.
Да и не в этом дело. Когда не было переменной var3, все отлично работало. Потом ввели var3, которая, ясное дело, может быть false или true. То есть, объект либо в список добавляется, либо нет - точно так же как было и раньше. Но вдруг появился глюк.
← →
Германн © (2014-11-03 02:28) [12]Юра.
Код
> boolean var1 = Выражение_1;
> boolean var2 = Выражение_2;
> boolean var3 = Выражение_3;
> if (var1 && var2 &&var3)
> что-то делаем;
и код
> boolean var1 = Выражение_1;
> boolean var2 = Выражение_2;
> boolean var3 = Выражение_3;
> if (var1 && var2) // Комментарий && var3)
> что-то делаем;
> System.out.println(var3);
>
отличаются имхо, двумя обстоятельствами.
Первое - то что в булевом выражении участвует разное количество переменных. (Но ты уже сказал, что ни в каком языке такие глюки недопустимы. Точнее никакие компиляторы такое не должны создавать).
Второе - то что в первом варианте переменная var3 используется до "что-то делаем", а во втором случае после.
Не знаю язву (слава богу, которого нет) и не знаком поэтому с компиляторами её. Так что присоединяюсь к
> DVM © (01.11.14 12:46) [5]
>
>
> > Юрий Зотов © (01.11.14 12:14) [4]
>
> А в Java нет такой штуки вроде отложенных вычислений, т.
> е код вычисляется не сразу а по мере необходимости в нем?
>
Только разумеется не в язве дело, а в её компиляторе.
Что получится, если строкуSystem.out.println(var3);
перенести выше по коду? Т.е. до "что-то делаем".
← →
sniknik © (2014-11-03 02:48) [13]> Потом ввели var3, которая, ясное дело, может быть false или true.
если верно про отложенные/оптимизатор, то var3 в "объективной реальности" нету, нужно рассматривать код вида -if (Выражение_1 && Выражение_2 && Выражение_1)
и т.д.
← →
Inovet © (2014-11-03 02:52) [14]Всё к тому же - к последовательности вычислений. Тем более что точно известно - Выражение_3 влияет на состояние, причём хитро и, видимо, неочевидно.
Так есть глюк?
if (var3 && var2 && var1)
← →
Inovet © (2014-11-03 02:55) [15]> [14] Inovet © (03.11.14 02:52)
И ещё дальше.
А так?
if (var1 & var2 & var3)
Это если в джаве такое имеет смысл.
← →
Inovet © (2014-11-03 02:56) [16]> [15] Inovet © (03.11.14 02:55)
Было вот к этому
if (var1 && var2) // Комментарий &&var3)
что-то делаем;
System.out.println(var3);
← →
Юрий Зотов © (2014-11-07 09:56) [17]И что вы думаете?
Переписал Выражение_3, сохранив его логику. Примерно что-то вроде этого:
not ((not B) or (not A)) вместо нормального A and B.
И заработало. No comments.
← →
Германн © (2014-11-08 01:44) [18]
> Юрий Зотов © (07.11.14 09:56) [17]
>
> И что вы думаете?
>
> Переписал Выражение_3, сохранив его логику. Примерно что-
> то вроде этого:
> not ((not B) or (not A)) вместо нормального A and B.
>
> И заработало. No comments.
>
Странно. Похоже на баг компилятора. И я с таким сталкивался. Но то действительно был недоделанный, но (имхо) единственный и в мире и во все времена компилятор Паскаля для MC51. Но что-то мне сомнительно, что и ты, Юр используешь столь же сырой компилятор. Ведь такой баг в достаточно широко используемом компиляторе был бы сразу обнаружен и исправлен.
Но раз заработало, то ...
Действительно No comments.
← →
Юрий Зотов © (2014-11-08 09:23) [19]> Германн © (08.11.14 01:44) [18]
Я и сам почти в шоке. Но делать серьезные выводы все же воздерживаюсь, потому что в процессе борьбы с багом в код были внесены еще и другие изменения. Например, были вынесены из цикла (а показанный выше код исполнялся в цикле) вычисления инвариантов, участвующих в выражениях 1-3. Конечно, инварианты должны были повлиять на скорость, но не на баг - но в итоге я не могу с уверенностью локализовать именно то мероприятие, после которого баг исчез.
← →
virex(home) © (2014-11-08 09:31) [20]>Юрий Зотов © (01.11.14 09:40) [0]
у меня еще чудесатее было: проект полностью построен как com+ приложение (клиентская и серверная часть), этакий толстый клиент, где серверная часть работает с бд mssql через ado
последнее время полезли ошибки (точно не вспомню, но со словом influense) притом без какой либо закономерности, и единственное временное решение - перезапуск сервера com+ приложений (а это надо выгонять всех юзеров)
в интернетах написано что глюк в bde (надо увеличить размер буфера), TClientDataSet (глючная midas.dll)
притом бде мы не используем
теперь внимание! убийца - дворецкий.
оказалось, что во все модули клиентской части (еще при сталине) прокрались визуальные компоненты-скины, и модули которые достаточно давно не менялись внезапно стали глючить через несколько лет. глюк - изза криво написанного компонента (скин формы) очень голодного на память
← →
virex(home) © (2014-11-08 09:34) [21]причем тот же клиент запущеный через citrix (ОЗУ 1Гб для сессии) никаких ошибок не выдавал
← →
kaif © (2014-11-08 13:42) [22]Этот код многопоточный или однопоточный?
← →
Юрий Зотов © (2014-11-08 14:49) [23]> kaif © (08.11.14 13:42) [22]
Вот это, в числе прочего, сейчас и выясняем. Сам по себе, код потоков не создает, но их может создавать сервер приложений. И хочется понять, что же это за "чудо" такое было и как его не допускать далее.
← →
Германн © (2014-11-09 02:43) [24]<offtop>
Чудеса, да и только.
> kaif © (08.11.14 13:42) [22]
Ашот, это действительно ты? Какими судьбами ты вновь тут? И где ты прятался всё это время?
:(
</offtop>
← →
Дмитрий С © (2014-11-10 09:51) [25]Спасибо за опыт, теперь буду осторожен!
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.075 c