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

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.022 c
15-1197744591
GeLLeR
2007-12-15 21:49
2008.01.20
Протестите прогу


15-1197639810
Fran
2007-12-14 16:43
2008.01.20
Дата прописью на калмыцком языке


2-1198162269
kyro
2007-12-20 17:51
2008.01.20
Установка новых шрифтов


15-1197749797
unknowing
2007-12-15 23:16
2008.01.20
UML. Опыт получения заданий от непрограммистов.


2-1197896910
Magedon
2007-12-17 16:08
2008.01.20
D2007 *.drf