Форум: "Потрепаться";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
ВнизГлюки в Дэлфе Найти похожие ветки
← →
Neft (2003-06-03 17:12) [0]Вот скажу честно, что видел как глючит делфя, это стопудов. Короче ставил там чтобы в переменную записывлось значение выражения, а она его как будто даже не видела, хотел протрасировать, так она его обозначет так, ну вы знаете как обозначются брейпоинты на эндах. короче пришлось это выражение запиывать в непрденазначенную для этого другую переменную. мне тут говорили что это может быть оптимизатор кода или чо то типа того гоняет, в общем интересно стало, что за фигня в датском государстве?
← →
Mike B. (2003-06-03 17:14) [1]Действительно фигня стопудов.
← →
Polevi (2003-06-03 17:21) [2]это хорошие глюки, добрые
← →
Юрий Зотов (2003-06-03 17:24) [3]А у меня дома лампочка глючит. Пока выключателем не щелкнешь - ни фига гореть не хочет. Стопудово!
А раз щелкнул - все равно не горит. И холодильник не работает. Потом сосед пришел - говорит, и у него то же самое. Позвонили еще соседям - и у них то же. Короче, во всем доме такая фигня. А потом само собой у всех загорелось. И холодильники включились. Стопудовый глюк! Честно, сам видел. Че за фигня в датском государстве?
← →
Digitman (2003-06-03 17:34) [4]или чо то типа того !
← →
DrPass (2003-06-03 17:57) [5]Ну ты типакороче там как тибе говорят аптимизатор кода походу выключи да? Ну дык там глюки типа прападут
← →
Neft (2003-06-03 20:09) [6]
> Юрий Зотов
неудачное сравнение, не видел чтобы у всез одновременно глючила делфя. а тот "сосед" не такой тупой как ты его выставил, может и побольше тебя сечет в программинге, и вообще, если это оптимизатор, то как обходить такие глюки, не отрубая его
← →
Юрий Зотов (2003-06-03 20:25) [7]> Neft © (03.06.03 20:09)
> не видел чтобы у всез одновременно глючила делфя
Уверяю Вас, такие "глюки", как Вы описали, есть именно у всех и именно одновременно.
> если это оптимизатор, то как обходить такие глюки, не отрубая
> его
Очень просто - надо писать ТАКОЙ код, чтобы НИ ОДНУ Вашу переменную оптимизатор не считал лишней. Тогда он ее и выбрасывать не будет.
← →
Neft (2003-06-03 20:56) [8]Вот код.
For I:=0 to n-1 do
Begin
For J:=I+1 to n-1 do
Begin
fLambda[0]:=fLambda[0]+KF.c[I,J]*XTemp[I,1]*XTemp[J,1];
fLambda[1]:=fLambda[1]+KF.c[I,J]*XTemp[I,0]*XTemp[J,1]+KF.c[I,J]*XTemp[I,1]*XTemp[J,0];
End;
End;
If fLambda[0]<>0 Then fLambda[0]:=-fLambda[1]/2/fLambda[0] Else fLambda[0]:=0;
if fLambda[0]>1 Then fLambda[0]:=1;//здесь вместо fLambda[0]должна была быть другая переменная, чтобы использоваться в следующем цикле.
For I:=0 to n-1 do
PNew[I]:=P[I]+fLambda[0]*(Z[I]-P[I]);
Ну так вот. Вот тебе пример. если тут реально что то используется неоптимально, то прошу рассказать в чем фишка.
P.S. Я понимаю, что компилятор выдает сообщение о неиспользуемых переменных, но чтобы не выполнять команду... в чем моя ошибка???
> Юрий Зотов
← →
Neft (2003-06-03 21:18) [9]Зотов ответь...
← →
Ihor Osov'yak (2003-06-03 21:35) [10]> здесь вместо fLambda[0]должна была быть другая переменная, чтобы использоваться в следующем цикле.
> короче пришлось это выражение запиывать в непрденазначенную для этого другую переменную.
Ты не вумничай, ты код приведи as is.. Тот, к которому у тебя якобы претензии..
← →
Neft (2003-06-03 21:38) [11]
> Ihor Osov"yak
а ты не груби
If fLambda[0]<>0 Then fLambda[0]:=-fLambda[1]/2/fLambda[0] Else fLambda[0]:=0;
if fLambda[0]>1 Then fLambda[0]:=1
а нужно было:
If Lambda[0]<>0 Then Lambda:=-fLambda[1]/2/fLambda[0] Else fLambda[0]:=0;
if Lambda>1 Then Lambda:=1
← →
Ihor Osov'yak (2003-06-03 21:47) [12]> а ты не груби
Ну-ну.. Это еще вопрос, кто первым начинает (не по отношению ко мне, а вообще)
> if Lambda>1 Then Lambda:=1
Откуда это лямбда узялось, где инициализируется, где потом используется? Повторяю - не упрямся, код приведи достаточный для анализа. Вместе с декларациями переменных, кодом присваивания начальных значений и областью ухода из области видимости..
← →
Юрий Зотов (2003-06-03 21:49) [13]> Neft
ОК, давайте разбираться. Раз уж речь идет об оптимизаторе, то надо иметь в виду, что с локальными и глобальными переменными он обращается по-разному. Значит, если Вы хотите услышать что-то конкретное, то Вы должны дать, как минимум, такую информацию по КАЖДОМУ используемому идентификатору:
1. Его реальное объявление;
2. Где это объявление стоит;
И, кроме того, где находится приведенный Вами код.
Жду.
← →
Neft (2003-06-03 21:53) [14]
> Юрий Зотов
приятно разговаривать с вежливым человеком ))
просто игнорировалась такая строчка
Lambda:=-fLambda[1]/2/fLambda[0];
без всяких ифов и с ними она просто не вычислялась, пришлось делать как сделал. я же говорю что это глюк. неужели никто ни разу не видел как,поднимаеш например одну строчку на позицию вверх и ошибка пропадает. я честно не вру.
← →
Ihor Osov'yak (2003-06-03 22:08) [15]2 Neft © (03.06.03 21:53)
Если Lambda потом нигде не использовалась, то оптимизатор выбрасывал ненужный код.
Чтобы однозначно ответить на этот вопрос, нужно увидеть фрагмент кода полностью, включая декларации и место ухода из области видимости, если это локальная переменная. Если это глобальная, или поле класса - то код, необходимый для анализа, будет значительно больше.
Зы. Это не глюк. Это нормальная работа оптимизирующего компилятора.
← →
Юрий Зотов (2003-06-03 22:08) [16]> Neft © (03.06.03 21:53)
> приятно разговаривать с вежливым человеком
Вы даже более чем правы. Мне тоже.
> я честно не вру.
Я знаю, что Вы не врете. Я даже это очень хорошо знаю. Речь идет не об этом, а о том, чтобы разобраться с причиной. Но я не могу ее показать, потому что не знаю, где и как у Вас объявлены все эти переменные - а именно от этого и зависит поведение оптимизатора.
Поэтому Вам нужно эти объявления привести, иначе я могу сказать только одно - никакой это не глюк, а совершенно нормальная (и очень полезная!) особенность оптимизируещего компилятора. Так что, Вы сами понимаете, что Ваш первый постинг, в котором прозвучала эдакая тинейджерская самоуверенность при полном незнании предмета, был просто смешным. Вот почему над ним и смеялись.
Давайте информацию о переменных - будем смотреть дальше.
← →
Neft (2003-06-03 22:14) [17]Function Search;
Var Proisv : TSyst;
I,J : Integer;
Grad : TPoint;
Z : Array of Real;
Syst : TSyst;
PNew : TPoint;
Res : Byte;
XTemp : Array of Array[0..1] of Real;
fLambda : Array[0..1] of Real;
Lambda была типа Real.
насчет тинейджерской самоуверенности. просто я пишу так как я разговариваю, только маты убираю. вы же понимаете что я в 22 года разговариваю на соответсвующим сленге.
← →
Ihor Osov'yak (2003-06-03 22:20) [18]2 Юрий Зотов
Я бы хотел ошибится, но мне кажется, что разговор с Neft нужно прекращать.
Если человека, как минимум, дважды просят привести исходный код, а он этого по каким-то загадочным причинам этого сделать не может, то.. я не настолько терпелив..
Приношу еще раз извинения за резкий выпад.
← →
Neft (2003-06-03 22:21) [19]
> Юрий Зотов
кстати прогу когда седня посмотрел, вспомнил, что я там недоделал)), так бы вообще пропустил
← →
Юрий Зотов (2003-06-04 01:26) [20]Что-то тут не срастается. Например, объявление
PNew : TPoint;
никак не вяжется с PNew[i] в коде. А объявления P вообще нет. И даже непонятно, все приведенные Вами объявления - локальные по отношению к коду, или внешние (например, локальные в охватывающей функции Search).
Так не годится, или давайте всерьез, или не будем тратить время.
← →
k-man (2003-06-04 08:32) [21]Можно ли параллельно задать вопрос по данной теме Юрию Зотову?
Вопрос такой: Часто при отладке пытаюсь смотреть значения разных переменных из окна Watch. Но бывает натыкаюсь на такое препятствие: вместо значения переменной получаю строку типа "Значение переменной недоступно из-за оптимизации"
Вопрос: Если я отключу ее (оптимизацию) будут ли значения этих переменных видны всегда? И еще: Это происходит далеко не со всеми переменными, Почему? И что дает это не показывание значений в коде?
← →
Юрий Зотов (2003-06-04 11:01) [22]IMHO, "значение переменной недоступно из-за оптимизации" означает, что транслятор построил код так, что в данном месте этой переменной в машинном коде просто не существует. То есть, не существует соответствующего ей адреса. Например, в цикле используется инвариантная переменная, поэтому код для ее вычисления транслятор разместил перед циклом, а уже готовый результат загнал в регистр, не размещая в памяти вообще никакой переменной. Или транслятор как-то еще изменил порядок операций и теперь он не совсем соответствует исходному коду. И т.д. - там целая наука на эту тему существует.
Естественно, так транслятор поступает далеко не всегда и далеко не со всеми переменными. Иначе это был бы уже не транслятор, а искусственный интеллект, да и железо этого не позволяет (скажем, количество регистров не бесконечно, чтобы хранить в них все подряд). Кстати, ведь и отладчик - это тоже не искуственный интеллект, а всего лишь программа, и она тоже не все умеет.
Если транслятор написан корректно (будем считать, что так оно и есть - а что нам остается?), то на работоспособности программы все это сказывается только в лучшую сторону. Но затрудняет отладку - поэтому и вводится опция отключения оптимизации (а иногда и опции типа "что оптимизировать - размер или скорость").
Если оптимизация отключена, то значения переменных будут видны в подавляющем большинстве случаев (почти всегда, особенно, если еще разрешить вызов функций для вычисления этих значений, есть и такая опция). Но могут быть какие-то особенности компилятора, которые в принципе не дают отладчику возможности вычислить эти значения при данном построении кода. Отсюда и идут чудеса типа "перенес на строку выше - стало показывать".
Все это не глюки, а нормальная работа компилятора. Нужно понять главное: компилятор - это переводчик с одного языка на другой, а даже в намного более богатых человеческих языках идеально точный перевод иногда бывает невозможен (да и не нужен, потому что, например, пословицу одного народа всегда можно заменить аналогичной пословицей другого народа). А уж задача художественного перевода (то есть, той же оптимизации) - это вообще перевод смысла, а не текста.
← →
k-man (2003-06-04 11:29) [23]Из Вашего ответа я могу сделать вывод о том
1) При отладке приложения оптимизацию можно исключить и включить только при окончательной сборке.(Тут параллельно возникает вопрос, а насколько полезна оптимизация для современных компьютеров с большим кол-вом памяти и высокой часотой процессора).
2) При правильном построении кода не будет этих самых "глюков".
(Тут опять возникает вопрос о том, что есть правильное построение кода....)
← →
Юрий Зотов (2003-06-04 11:50) [24]1. Я всегда так и делаю.
2. Если уж мы пишем не на ассемблере, да еще используем RAD, то говорить об особой уж там оптимизации как-то все же немного странно. Поэтому я стараюсь писать код, руководствуясь, прежде всего, критериями надежности, читабельности, простоты, легкости его будущей модификации, универсальности, повторной используемости и пр. Но и в то же время буквально в каждом слове и в каждой строке думаю, а как это воспримет компилятор и во что это в итоге превратится - то есть, оптимизирую код САМ (кстати, это и есть лучший способ оптимизации, потому что транслятор не гений и много он там наоптимизировать все равно не сможет, да и оптимизировать уже оптимизированный программистом код ему проще, и вероятность внесения им глюков при этом тоже меньше).
Иногда, конечно, бывают какие-то куски кода, где, например, скорость или память выходят на первый план - ну так к этим кускам и подход другой.
← →
NailMan (2003-06-04 13:35) [25]Ну тогда я тоже задам такой вопрос касающийся глюков Дельфинариума:
В функции есть цикл, в котором создается объект.
Все бы хорошо, но счетчик цикла почему то не инициализируется с нуля хотя указано прямо:
for i:=0 to ActorCount-1 do ...
var i:integer;
переменная i локальная, в теле for она не изменяется и работает только как счетчик, тоесть не используется для индексации.
Ловлю значение в i при пошаговом выполнении программы и наблюдаю что при первом входе в цикл переменная i либо заблокирована(при наведении мыша значение не показывается) либо в ней значение ActorCount и дальше увеличивается.
Сделал для счетчика переменную NN:integer - все нормально.
Цикл выполняется как положено, с нуля.
Ну и что это за баг такой? Кто мне объяснит?
← →
k-man (2003-06-04 13:40) [26]Опять таки я думаю тебе надо привести полный код функции
со всеми объявлениями.
Говоришь, что если другой идентификатор то все нормально?
Посмотри где у тебя еще может быть описана i.
← →
Юрий Зотов (2003-06-04 13:47) [27]В первом случае компилятор строит код с декрементированием регистра ECX (или EDX) и с переходом JZ (или JNZ) - то есть, как нисходящий. Это хорошо видно в окне CPU и это действительно оптимально. Как он строит его во втором случае - зависит от того, где объявлена переменная NN и как она используется, помимо счетчика цикла.
← →
Ihor Osov'yak (2003-06-04 13:57) [28]2 NailMan © (04.06.03 13:35)
Поставьте точку останова в начале цыкла и после ее срабатывания сделайте CTRL_ALT_C. Если в ассемблере немного разбираетесь, сразу все станет ясно.. Если нет - то в общих чертах дело обстоит так:
для цыклов for если переменная цыкла не используется в цыкле, то в регистр ecx заносится количество выполнений цыкла, а потом при каждом прохождении цыкла делается декремент ecx. Условие окончания цыкла - равенство ecx нулю. Почему компилятор для этого случая делает так? наверное потому, что сравнение с нулем происходит быстрее. Вернее, даже сравнения не нужно - просто анализируется соотв. флаг из регистра флагав после декремента.. И анализ идет не отдельной командой, а командой условного перехода. То есть код получается достаточно компактный и эффективный..
Зы - см. ЮЗ, там где он говорил о переводе смысла, а не о дословном переводе..
← →
NailMan (2003-06-04 14:06) [29]To -> k-man ©
полный код привести не могу, так как функция габаритная, да и глюкает почти в самом начале, привожу краткий кусок:
Function TScene.Load(name:string):boolean;
var i:integer;
Z:integer;
st:string;
begin
... открываю файл сцены и считываю переменные ActorCount, LightCount
//ActorCount считывается со значением 2
for i:=0 to ActorCount-1 do
begin
z:=GetFreeIndex(FREE_ACTOR);
Actor[Z]:=TActor.Create;
...считывание строки с именем конфига в st и параметры расположения в мире
Actor[Z].LoadINI(st);
Actor[Z].MoveToS(0,0,0);
end;
For i:=0 to LightCount-1 do
begin
... считывание данных о источнике света и установка их в i-й источник Light[i]
end;
end;
Собсно глюкает именно в первом цикле c Actor. Второй цикл проходит нормально. Добавляю в varnn:integer;
и юзаю его в первом цикле - все нормально.
Посмотри где у тебя еще может быть описана i.
В глобальных переменных никаких счетчиков не описано. Юзается именно локальная.
To -> Юрий Зотов ©
Как он строит его во втором случае - зависит от того, где объявлена переменная NN и как она используется, помимо счетчика цикла.
как я уже говорил NN есть только в локальных переменных данной функции. Нигде больше я не создавал переменных с подобным именем.
Ну что скажете, мастера?
← →
evvcom (2003-06-04 14:34) [30]Тебе она нужна эта i или NN? Ну и чего ты голову всякими пустяками забиваешь? Ну наоптимизировал там чего-то компилятор, что прога не работает разве? Разберись лучше с ассемблером, и тогда на подобные вопросы сможешь сам отвечать без труда.
← →
NailMan (2003-06-04 14:40) [31]To -> evvcom ©
дык работать-то работает, важен сам факт. Я вообще пробовал черезrepeat until
и все прекрасно работает с одной i.
← →
Danilka (2003-06-04 14:44) [32]NailMan © (04.06.03 14:06)
а в каком месте в этом коде точка останова обозначается как "ну вы знаете как обозначются брейпоинты на эндах"?
:))
что-то я не вижу таких мест в этом коде.
← →
evvcom (2003-06-04 14:45) [33]Ну и хорошо, что работает. Компилятор видит, что тебе в этом коде эта i нужна только как счетчик безо всякой индексации и др. расчетов. Вот он и оптимизирует насколько может. Возможно, что в первом случае у него хватило регистров для хранения счетчика, а во втором уже не хватило, и он отвел под эту переменную место в памяти. Соответственно и код уже другой получился.
← →
McSimm (2003-06-04 15:04) [34]Господа, темы с радостными известиями о том что наконец-то найдены глюки в компиляторе поднимались уже очень много раз.
(Причем, похоже, первое место по частоте здесь занимает обратный отсчет в цикле :)
И всегда выяснялось, что никаких глюков на самом деле нет, а имеет место быть нормальная работа оптимизатора кода.
← →
McSimm (2003-06-04 15:16) [35]Вот, думаю в тему будет.
Не далее как вчера некоторое время с удивлением рассматривал фрагмент кода (причем довольно типичный):
K := Arr^[J]; //1
Arr^[J] := Arr^[I]; //2
Arr^[I] := K; //3
Удивляло в этом фрагменте то, что строка //1 не имела исполняемого кода, отладчик проходит только по //2 и по //3.
При этом значение переменной K можно было посмотреть только в строке //3 и оно было верным!
Не правда ли, на первый взгляд кажется загадочным :)
Оказалось все очень просто:
if Arr^[J] < Arr^[I] then // <-здесь отгадка :)
begin
K := Arr^[J];
Arr^[J] := Arr^[I];
Arr^[I] := K;
end;
Чтобы выполнить сравнение компилятор взял значение Arr^[J] в регистр, поскольку выполнить сравнение с двумя индексируемыми ячейками памяти непосредственно он не имеет возможности.
Оптимизатор справедливо рассудил, что значение в регистре вполне заменит использование переменной K и удалил саму переменную и код. А умный отладчик сумел в строке //3 распознать значение, используемое вместо переменной K.
← →
Юрий Зотов (2003-06-04 15:38) [36]> NailMan © (04.06.03 14:06)
> как я уже говорил NN есть только в локальных переменных данной
> функции
Вот этого Вы как раз и не говорили, а говорили вот что:
"Сделал для счетчика переменную NN:integer"
Заметьте - здесь ничего не сказано о том, локальная она, или глобальная, используется ли где-то еще, или нет. А как раз от этого многое и зависит.
Ну, ладно, сказали - и хорошо. Я воспроизвел Вашу ситуацию в D5 (с включенной оптимизацией) на таком макете:
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
for i := 0 to 5 do
MessageBeep(0); // Здесь BreakPoint
end;
И затем переменная i заменялась на переменную NN. Так вот, в обоих случаях я прекрасно вижу в отладчике значение счетчика цикла и оно меняется от 6 до 1. А в окне CPU вижу, что в обоих случаях компилятор строит АБСОЛЮТНО одинаковый код:
mov ebx, $00000006 ; начальное значение счетчика цикла в ebx
push $00 ; параметр MessageBeep заталкивается в стек
call -$00000799 ; вызов MessageBeep
dec ebx ; декремент счетчика
jnz TForm1.Button1Click + $6 ; переход на начало по флагу нуля
Что, собственно, и следовало ожидать.
Хорошо, теперь делаем переменную NN глобальной и запускаем тот же самый код. Во-первых, сразу же получаем предупреждение компилятора о том, что этот код он не может оптимизировать. Во-вторых, теперь отладчик показывает, что NN меняется от 0 до 5 - то есть компилятор построил код "в лоб". В-третьих, именно такой "дословный перевод" мы и видим в окне CPU (код не привожу, лень переписывать, хотите - проверьте сами).
Что, собственно, тоже и следовало ожидать.
Делаем выводы:
1. Воспроизвести Вашу ситуацию не удалось. Думаю, потому, что Вы привели неточную или неполную исходную инфоромацию.
2. Никаких глюков не обнаружено.
P.S.
Циклы while и repeat - это другая статья, там нет никаких счетчиков и поэтому к ним такая оптимизация не относится.
← →
Neft (2003-06-04 19:49) [37]короче я уже заколебался втавляьб модуль, не влазит даже пятая часть
← →
Neft (2003-06-04 19:51) [38]unit WolfUnit;
interface
Uses GoldSech;
Type
{
← →
Neft (2003-06-04 19:54) [39]Function Search;
Var Proisv : TSyst;
I,J : Integer;
Grad : TPoint;
Z : Array of Real;
Syst : TSyst;
PNew : TPoint;
Res : Byte;
XTemp : Array of Array[0..1] of Real;
fLambda : Array[0..1] of Real;
Begin
SetLength(Proisv,n,n+1);
SetLength(Grad,n);
SetLength(PNew,n);
SetLength(Z,2);
For I:=0 to n-1 do
Begin
For J:=0 to I do
Begin
If I=J Then
Proisv[I,J]:=KF.C[J,I]*2
Else
Proisv[I,J]:=KF.C[J,I];
End;
For J:=I+1 to n-1 do
Begin
Proisv[I,J]:=KF.C[J,I];
End;
Proisv[I,n]:=KF.D[I]
End;
SetLength(Syst,m,n+1);
For I:=0 to m-1 do
For J:=0 to n-1 do
Syst[I,J]:=Ogr.A[I,J];
For I:=0 to m-1 do Syst[I,n]:=Ogr.B[I];
GradCalc(P,Grad,Proisv);
SM(Syst,m,n,Z,Res,Grad);
SetLength(XTemp,n);
For I:=0 to n-1 do
Begin
XTemp[I][0]:=P[I];
XTemp[I][1]:=Z[I]-P[I];
End;
For I:=0 to n-1 do
Begin
XTemp[I][1]:=Z[I]-P[I];
End;
//fLambda[0] -
← →
k-man (2003-06-04 20:04) [40]2Neft
в таких случаях модуль делят.
Страницы: 1 2 вся ветка
Форум: "Потрепаться";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.03 c