Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.01.20;
Скачать: [xml.tar.bz2];

Вниз

Результат трехчасовых поисков ошибки в проекте :)   Найти похожие ветки 

 
Riply ©   (2007-12-10 17:08) [0]

Здравствуйте !
Допустим, у нас есть две ф-ии:

function Funct1(var Param: integer): integer;
begin
if Param = 0 then inc(Param, 1);
Result := Param;
end;

function Funct2(var Param: integer): integer;
begin
if Param = 0 then inc(Param, 2);
Result := Param;
end;


Что мы увидим в сообщении:

Param := 0;
ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));


Чур Delphi не пользоваться :)
Пол дня убила на поиск ошибки, зато новые знания :)


 
Palladin ©   (2007-12-10 17:10) [1]

3 и увидим


 
Rouse_ ©   (2007-12-10 17:10) [2]

1?


 
Alkid ©   (2007-12-10 17:11) [3]

Мда, а ещё кто-то за конструкции вида i = i++ + 1 С/C++ извращением считает...


 
Palladin ©   (2007-12-10 17:11) [4]

ой... 4 :)


 
Сергей М. ©   (2007-12-10 17:11) [5]


> Пол дня убила на поиск ошибки


Бедняга).. Целых пол-дня !!

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


 
Rouse_ ©   (2007-12-10 17:12) [6]

А, не, там еще сложение ж у тебя :)
Двойку увидим :)


 
Riply ©   (2007-12-10 17:13) [7]

Верных ответов, пока, нет :)


 
Palladin ©   (2007-12-10 17:14) [8]


> Rouse_ ©   (10.12.07 17:12) [6]

А var не заметил? :)

первая функция возвратит 1, изменит значение переменной на 1
вторая функция возвратит 3

1+3=4


 
Riply ©   (2007-12-10 17:14) [9]

> [6] Rouse_ ©   (10.12.07 17:12)

Когда отправляла, твоего ответа не видела.
Правильно !
:)


 
Rouse_ ©   (2007-12-10 17:14) [10]


> Верных ответов, пока, нет :)

Проверил - показывает двойку :)


 
Rouse_ ©   (2007-12-10 17:15) [11]


> вторая функция возвратит 3

Нет, т.к. param уже будет не 0 а единица :)


 
Palladin ©   (2007-12-10 17:16) [12]

млин... условие if забыл... розыч, посыпаю голову пеплом
2 возвратит


 
Riply ©   (2007-12-10 17:16) [13]

>[5] Сергей М. ©   (10.12.07 17:11)
> Бедняга).. Целых пол-дня !!
> Нет бы сразу пройтись отладчиком и выяснить, где таятся грабли)

В свое оправдание скажу, что настоящая ситуация выглядит не совсем так :)
Это ее суть :)


 
Reindeer Moss Eater ©   (2007-12-10 17:16) [14]

2


 
Riply ©   (2007-12-10 17:18) [15]

Я когда искала ошибку, на автомате полагала, что
сначала выполниться Funct1, а потом Funct2


 
Riply ©   (2007-12-10 17:20) [16]

> [12] Palladin ©   (10.12.07 17:16)
> [14] Reindeer Moss Eater ©   (10.12.07 17:16)

Я всегда говорила, что настоящие программисты здесь :)
Но Rouse_ первым увидел подвох :)


 
Rouse_ ©   (2007-12-10 17:21) [17]


> на автомате полагала, что
> сначала выполниться Funct1, а потом Funct2

Так оно так и происходит :) Сначала первая выполняется а потом вторая :)


 
Palladin ©   (2007-12-10 17:22) [18]


> Riply ©   (10.12.07 17:20) [16]

:) я if не учел при внутреннемозговом исполнениии...
вывод: пиво - враг интерпритации действий...


 
Rouse_ ©   (2007-12-10 17:22) [19]


> пиво - враг интерпритации действий...

Ты на работе под пивом кодишь? Суров... :)


 
Сергей М. ©   (2007-12-10 17:23) [20]


> Riply ©   (10.12.07 17:16) [13]


> настоящая ситуация выглядит не совсем так


А неважно как она выглядит)
Трассировка мгновенно расставила бы все точки над i)


 
Palladin ©   (2007-12-10 17:23) [21]


> Так оно так и происходит :) Сначала первая выполняется а
> потом вторая :)

:) вот только во второй значение уже другое ибо var...
диагноз: ай ай ай... :)


 
Palladin ©   (2007-12-10 17:24) [22]


> Rouse_ ©   (10.12.07 17:22) [19]

а кто сказал что я сейчас кодю? :) я в форуме сидю... :)

вот... пытался интерпретировать... и не замечая мелких деталей рванувшись к цели - промазал :)


 
Riply ©   (2007-12-10 17:24) [23]

> [17] Rouse_ ©   (10.12.07 17:21)

> Так оно так и происходит :) Сначала первая выполняется а потом вторая :)

???

> [18] Palladin ©   (10.12.07 17:22)
> :) я if не учел при внутреннемозговом исполнениии...
> вывод: пиво - враг интерпритации действий...

:)


 
guav ©   (2007-12-10 17:26) [24]

Напоминает
int i = 5;
cout << ++i + ++i;
где разные компиляторы разный результат дают


 
Rouse_ ©   (2007-12-10 17:26) [25]


> Riply ©   (10.12.07 17:24) [23]
> ???

Ну ты посмотри в отладчике, при вызове ShowMessage сначала происходит выполнение первой функции, потом передается управление на вторую, потом конкатенация и вызов IntToStr :)

Unit38.pas.118: ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));
0045EF3F 8D45FC           lea eax,[ebp-$04]
0045EF42 E8C1FFFFFF       call Funct1
0045EF47 8BD8             mov ebx,eax
0045EF49 8D45FC           lea eax,[ebp-$04]
0045EF4C E8C3FFFFFF       call Funct2
0045EF51 03D8             add ebx,eax
0045EF53 8BC3             mov eax,ebx
0045EF55 8D55F8           lea edx,[ebp-$08]
0045EF58 E8AF98FAFF       call IntToStr


 
stone ©   (2007-12-10 17:30) [26]


> Riply ©   (10.12.07 17:08)  

Задачку про буратино и яблоки знаешь?


 
DiamondShark ©   (2007-12-10 17:34) [27]


> Чур Delphi не пользоваться :)

А без этого -- гадание на кофейной гуще.
Потому что порядок, в котором вызовутся функции никем не гарантирован.


> guav ©   (10.12.07 17:26) [24]
> Напоминает
> int i = 5;
> cout << ++i + ++i;
> где разные компиляторы разный результат дают

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


 
Palladin ©   (2007-12-10 17:36) [28]


> DiamondShark ©   (10.12.07 17:34) [27]

Эт почему не гарантирован? Какой то delphi компилятор строит выполнение выражения справа налево чтоли?


 
Riply ©   (2007-12-10 17:36) [29]

> [26] stone ©   (10.12.07 17:30)
> Задачку про буратино и яблоки знаешь?

Неа.

> [27] DiamondShark ©   (10.12.07 17:34)
> Потому что порядок, в котором вызовутся функции никем не гарантирован.

А можно аргументировать ?


 
Rouse_ ©   (2007-12-10 17:39) [30]

Кстати, а у кого FreePascal есть? Проверьте там очередность вызова.


 
Riply ©   (2007-12-10 17:44) [31]

> [25] Rouse_ ©   (10.12.07 17:26)
> Ну ты посмотри в отладчике,

Смотрю и не могу понять, почему тогда возвращается 2 ?


 
Palladin ©   (2007-12-10 17:46) [32]


> Rouse_ ©   (10.12.07 17:39) [30]

точно такая же... но я бы удивился если бы это было не так..


> Riply ©   (10.12.07 17:44) [31]

потому что параметр передан по ссылке, а не по значению... соответственно когда выполнилась функция func1 само значение param уже 1 соответственно при переходе к исполнению func2 оно тоже 1


 
Palladin ©   (2007-12-10 17:47) [33]

param имеется ввиду сама переменная парам а не та что в параметрах


 
Германн ©   (2007-12-10 17:47) [34]


> Смотрю и не могу понять, почему тогда возвращается 2 ?
>

Я тоже не могу понять.


 
Германн ©   (2007-12-10 17:49) [35]


> Palladin ©   (10.12.07 17:47) [33]
>
> param имеется ввиду сама переменная парам а не та что в
> параметрах
>

А как же АСМ в Rouse_ ©   (10.12.07 17:26) [25]?


 
Riply ©   (2007-12-10 17:51) [36]

> [32] Palladin ©   (10.12.07 17:46)
> потому что параметр передан по ссылке, а не по значению...
>соответственно когда выполнилась функция func1 само значение param уже 1
> соответственно при переходе к исполнению func2 оно тоже 1

но тогда(при переходе к исполнению func2 оно тоже 1) func2 ничего бы не изменила и мы бы увидели 1


 
Rouse_ ©   (2007-12-10 17:51) [37]


> Смотрю и не могу понять, почему тогда возвращается 2 ?

Ок, разжую :)

Unit38.pas.117: Param := 0;
0045EF3A 33C0             xor eax,eax // чистим Param
0045EF3C 8945FC           mov [ebp-$04],eax // помещает его на стек
Unit38.pas.118: ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));
0045EF3F 8D45FC           lea eax,[ebp-$04] // готовим ссылку на параметр
0045EF42 E8C1FFFFFF       call Funct1 // дергаем функцию
0045EF47 8BD8             mov ebx,eax // сохраняем результат функции во временном регистре (в ebp-$04 также лежит единица, т.к. ByRef)
0045EF49 8D45FC           lea eax,[ebp-$04] // готовим ссылку на параметр
0045EF4C E8C3FFFFFF       call Funct2 // дергаем вторую функцию
// она также вернула единицу т.к. не выполнилось условие if Param = 0 then
0045EF51 03D8             add ebx,eax // складываем оба результата
0045EF53 8BC3             mov eax,ebx // ну а дальше IntToStr и ShowMessage
0045EF55 8D55F8           lea edx,[ebp-$08]
0045EF58 E8AF98FAFF       call IntToStr
0045EF5D 8B45F8           mov eax,[ebp-$08]
0045EF60 E87BE5FCFF       call ShowMessage


 
Rouse_ ©   (2007-12-10 17:52) [38]


> func2 ничего бы не изменила и мы бы увидели 1

Не изменила - она вернула то, что ей было переданно, а передано ей было уже 1 а не ноль :)


 
Palladin ©   (2007-12-10 17:54) [39]


> Riply ©   (10.12.07 17:51) [36]

ну мля... в параметрах исполнения func один передается не значение 0, а ссылка на саму переменную, и именна сама переменная после отработки функции меняет значение, после идет исполнение func два, которой уже передано (и кстати не важно как var или const или просто в стек засунуто) значение 1 потому что func один уже поменяла значение...


 
Riply ©   (2007-12-10 17:54) [40]

> [37] Rouse_ ©   (10.12.07 17:51)
> Ок, разжую :)

Спасибо.



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

Форум: "Прочее";
Текущий архив: 2008.01.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.111 c
15-1197744595
@!!ex
2007-12-15 21:49
2008.01.20
Охлаждение материнской платы.


8-1172775788
Radgar
2007-03-01 22:03
2008.01.20
Громкость


2-1198076609
new_user)
2007-12-19 18:03
2008.01.20
Как перемножить


15-1197517281
Slider007
2007-12-13 06:41
2008.01.20
С днем рождения ! 13 декабря 2007 четверг


9-1165994367
Аццкий_рыцарь
2006-12-13 10:19
2008.01.20
Options.ini





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский