Форум: "Начинающим";
Текущий архив: 2011.04.24;
Скачать: [xml.tar.bz2];
ВнизПринтер "портит" выполнение программы? Найти похожие ветки
← →
Abcdef123 (2010-12-22 06:31) [0]Здравствуйте, Мастера. Заранее извиняюсь, если мой вопрос послан не по теме данного форума.
Столкнулась с такой проблемой. Программа очень давняя, работала нормально, проблема возникла только у клиента сейчас, когда они купили новый принтер (HP). В одном месте программы дает ошибку Number out of range. Если проигнорировать ошибку и попробовать запустить то же самое (не перезагружая проект), то второй раз выполняется номально. Со старым принтером вообще нормально работает!!!
Вот сейчас детали:трассировка ошибки показала место, где получается "большое" число. В процедуре объявлена переменная типа Currency и ей присваивается некое значение, вычисляемое по формуле, на основе данных таблицы. Так вот, первый раз похоже значение это не вычисляется (это я так полагаю), поскольку интересное значение этой переменной получается: –922337203685477.5808 (то есть минимальное значение, которое может иметь этот тип). Знаний насчет драйвера принтера у меня недостаточно. Вот и думаю, возможно ли, что драйвер принтера каким то образом "портить" программу? И если да, то каким образом второй раз ошибки нет, присваивается нужное рассчитанное значение этой переменной. Пожалуй, на этом описание закончу, если что-то нужно подробнее сообшить - спросите. Возможно, что кто-то встречался с подобной проблемой. Может я вообще не там ищу причину? Буду рада любому дельному совету. Заранее спасибо!
← →
brother © (2010-12-22 07:40) [1]Тут не принтер виноват...
> Если проигнорировать ошибку и попробовать запустить то же
> самое (не перезагружая проект), то второй раз выполняется
> номально.
наводит на мысль, что прога что-то не верно прощитывает... а потом (возможно второй проход просчета) все ок...
← →
brother © (2010-12-22 07:42) [2]можно ли попробовать со старым принтером опять? или любыми другими?
← →
Abcdef123 (2010-12-22 07:49) [3]To [2][ так в том то и дело, что они меняли принтеры для всяких комбинаций экспериментов. Со старым работает четко ВСЕГДА, как часы, даже сейчас.А как только меняют на новый - такая вот проблема. Как только снова меняют на старый - опять хорошо проходит. Поэтому и наталкивает на мысль что в принтере проблема. Иначе по логике прога всегда бы сбоила.
← →
Ega23 © (2010-12-22 08:04) [4]
> Поэтому и наталкивает на мысль что в принтере проблема.
Не думаю. Скорее, данная ошибка существует всегда, вот только явно проявляется с новым принтером.
Логи спасут мир.
← →
Abcdef123 (2010-12-22 08:27) [5]To [4]. Извините за примитивный вопрос - что такое логи? Я посмотрела в инете - типа как трассировка. Я обычно трассировку делаю - в коде, где ошибка - я добавляю мессаджи со сплошной нумеровкой (если надо то со значеними переменных, какие вызывают подозрения на ошибку). И таким образом нахожу строку, на которой споткнулась программа. Такой подход сойдет на лог? Или логи - это что то более точное??
← →
Ega23 © (2010-12-22 08:42) [6]
> Такой подход сойдет на лог?
В целом - да. Хотя, на пой взгляд, это более утомительно.
← →
MonoLife © (2010-12-22 08:51) [7]
>Abcdef123 (22.12.10 06:31)
> поскольку интересное значение этой переменной получается:
> –922337203685477.5808
инициализировать переменную перед этим не пробовали?
← →
Abcdef123 (2010-12-22 09:13) [8]To [7] Пробовала, присвоила значение ноль. Не помогло :-(
← →
brother © (2010-12-22 09:17) [9]так исходники доступны? показываем тогда...
← →
Abcdef123 (2010-12-22 09:23) [10]сразу оговорюсь, чтоб помидорами не забросали, прога ну очень старая, не моя. Я просто сопровождаю пакет.
Вот отрывок из кода, где сбоит:
procedure proc1;
var
rlBase, rlMulti, rlBaseDM, rlMultiDM, rlAmount : Currency;
begin
{Здесь некотовый код, определены значения переменных rlBase, rlMulti, rlBaseDM, rlMultiDM. Кстати, значение rlBaseDM, rlMultiDM порой бывают равны нулю}
rlAmount := CalcProportionAsAmount(rlMulti, tblDetail.FieldByNamе("INV_AMT").AsFloat, rlBase) -
CalcProportionAsAmount(rlMultiDM, tblDetail.FieldByName("INV_MEMO").AsFloat, rlBaseDM);
{вот тут значение rlAmount большое (неправильное), которое на следующей строке вызывает ошибку, когда пытаемся присвоить это значение в поле таблицы.}
tblHeader. FieldByName("TOTAL").AsFloat := FieldByName("TOTAL").AsFloat - rlAmount; //на этой строке выскакивает ошибка
end;
function CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount : Currency) : Currency;
var
rlPercent : Real;
begin
try
rlPercent := (rlSubTotal / rlTotal);
except
rlPercent := 0;
end;
CalcProportionAsAmount := rlAmount * rlPercent;
end;
← →
MonoLife © (2010-12-22 09:42) [11]А ничего, что тип rlPercent = Real, а rlAmount (в функции) - Currency?
← →
Abcdef123 (2010-12-22 09:51) [12]To [11]: Это вопрос или такой стиль утверждения, что тут и ошибка? Честно говоря, я не думала, что оперировать с карренси и реал может вызвать ошибку. Я полагала, что эти типа совместимы в математических операциях.
← →
Ega23 © (2010-12-22 09:54) [13]
> Я полагала, что эти типа совместимы в математических операциях.
Совместимы, да не совсем.
← →
Abcdef123 (2010-12-22 10:02) [14]To [13] То есть это и создает проблему? То есть вы уверены, что замена типа 100% исправит ситуацию? Просто поскольку пробоема не у нас,а на стороне (у клиента) сами понимаете, хотелось бы уже ограничить количество выездов для эксперимента. Поэтому, если это как одна из возможных идей, может еще есть предположения в ошибке?
Хорошо, я поменяю тип rlPercent на сарренси. Но, не могли бы вы пояснить, почему так нелогично работает? То есть при первом заходе сбоит, а при втором нормально. Это ж одна и та же процедура выполняется. А со старым принтером вообще нормально. Вот это никак в логику не укладывается.
← →
MonoLife © (2010-12-22 10:16) [15]
> То есть вы уверены, что замена типа 100% исправит ситуацию?
нет.
к слову, из справки (D7):
When mixed with other real types in assignments and expressions, Currency values are automatically divided or multiplied by 10000.
← →
Ega23 © (2010-12-22 10:28) [16]
> То есть вы уверены, что замена типа 100% исправит ситуацию?
Я ни в чём не уверен. Даже в своей будущей половой ориентации.
Но практика показывает, что чем меньше "тёмных" мест и небезопасного кода - тем проще детектируются ошибки (а в идеале - вообще не возникают).
← →
brother © (2010-12-22 10:31) [17]
function CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount : Currency) : Currency;
begin
try
result:= rlAmount * (rlSubTotal / rlTotal); // поставить тут бряк и посмотреть какие значения...
except
result:= 0;
end;
end
← →
Abcdef123 (2010-12-22 10:37) [18]To [17]: Хорошо, попробую! Спасибо! Но, наверно, сегодня не получится проверить у клиента на месте. Так что сообщу о резульататах позже. А пока, спасибо всем! Если есть еще предложения, чтоб уж заодно все проверить - милости просим. :-)
← →
han_malign (2010-12-22 11:23) [19]- попробуй вот это заклинание:
asm FINIT end;
а потом вот здесь
rlAmount := CalcProportionAsAmount(...)function CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount : Currency) : Currency;
begin
asm FINIT end;
try
result:= rlAmount * (rlSubTotal / rlTotal);
except
result:= 0;
end;
end
- не раз и не два, встречал случаи когда что-то-где-то выводило из себя сопроцессор...
← →
turbouser © (2010-12-22 12:33) [20]Если уж Currency - так надо везде Currency.
И FieldByName(xxx).AsCurrency и rlPercent : Currency;
← →
Anatoly Podgoretsky © (2010-12-22 13:40) [21]> Abcdef123 (22.12.2010 09:13:08) [8]
Не помогло, что?
← →
Abcdef123 (2010-12-23 04:43) [22]To [21] мне посоветовали "инициализировать переменную перед этим не пробовали?". И я ответила, что пробовала инициализировать, но проблема всё та же.
To [20] простите, может вопрос примитивный, но я правда не знаю, что это вы предлагаете "asm FINIT end;" Что это?
← →
brother © (2010-12-23 05:21) [23]> "asm FINIT end;" Что это?
http://forum.shelek.ru/index.php/topic,8892.0.html
1. finit сбрасывает состояние FPU в дефолтовое и, как следствие, переписывает регистр управления.
← →
Abcdef123 (2010-12-23 05:49) [24]To [23] большое спасибо за ответ!!! Поскольку этого не знала, то еще небольшой вопросик - это сбрасывание в дефолтовое состояние распространяется только на процесс работы моего проекта (если я вставлю этот код), или даже после окончания работы с моей программой это дефорлтовое состояние остается? Если остается, то я боюсь, а вдруг это сбрасывание повредит работу других приложений у клиента? (опять же извиняюсь за возможно глупый вопрос)
← →
brother © (2010-12-23 05:55) [25]код из [17] или [19] опробован?
← →
Abcdef123 (2010-12-23 06:30) [26]To [25] нет еще, к сожалению. И похоже до нового года поездка к клиентам на это тестирование не состоится. :-(
А насчет проверки [19] я задала вопрос [24], потому что если вдруг после такой проверки какое то другое приложение у клиента вдруг будет глючить, то мне бошку оторвут за такие эксперименты.
← →
brother © (2010-12-23 06:54) [27]тогда, я "умываю руки" ...
← →
Abcdef123 (2010-12-23 07:54) [28]To [27]. Почему? А что на [24] вопрос никто не знает ответа?
← →
12 © (2010-12-23 10:17) [29]Поставить левый принтер. из стандартных, назначить печать в файл, напечатать.
Ошибка повторилась?
showmessage все параметры в CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount
или числитель большой или знаменатель маленький
← →
12 © (2010-12-23 10:20) [30]кстати
try
rlPercent := (rlSubTotal / rlTotal);
except
rlPercent := 0;
end;
а какой тут Except?
кроме /0
ну так и писать надо
if rlTotal <> 0 then ...
else Result := 0;
← →
han_malign (2010-12-23 10:40) [31]
> Если остается, то я боюсь, а вдруг это сбрасывание повредит работу других приложений у клиента?
- нет, состояние процессора/сопроцессора изменяется только в контексте текущего процесса/потока(при переключении между потоками состояние регистров сохраняется и соответственно восстанавливается).
Но некоторые нехорошие драйвера и/или сторонние библиотеки, к которым ваше приложение явно или неявно(например они могут цеплять system-wide hook-и, а сейчас еще каждая собака балуется rootkit-ами(из лучших побуждений конечно)) обращается - могут запарывать состояние регистров именно в контексте вашего процесса...
← →
Abcdef123 (2010-12-23 10:52) [32]To [31]: Огромное спасибо за ответ. Мне это было важно знать! Теперь спокойно не боясь за последствия могу это использовать!
← →
Ega23 © (2010-12-23 10:54) [33]
> а какой тут Except?
> кроме /0
Divizion By Zero
Range Check Error
← →
han_malign (2010-12-23 11:01) [34]
> ну так и писать надо
> if rlTotal <> 0 then ...
> else Result := 0;
- а вот тут ты не совсем прав - currency(1E13)/0.0001, хотя это конечно экстремальный случай...
← →
12 © (2010-12-23 11:10) [35]
> Range Check Error
> currency(1E13)/0.0001
так это надо оставить для обработчика выше,
чтоб потом не ломать голову откуда такие числа при прогоне.
А деление проверяется на зеро заранее.
← →
Ega23 © (2010-12-23 11:12) [36]
> А деление проверяется на зеро заранее.
Не всё так просто
← →
brother © (2010-12-23 11:12) [37]> А деление проверяется на зеро заранее.
ты не погорячился?
try там вполне подходит...
← →
12 © (2010-12-23 11:19) [38]вообщем, я б так написал
function TryCalcProportionAsAmount(const rlTotal, rlSubTotal, rlAmount : Currency; var MyResult: Currency) : Boolean;
begin
Result := true;
try
if rlTotal <> 0 then
MyResult := rlAmount * (rlSubTotal / rlTotal) else
MyResult := 0;
except
result:= false;
Raise;
end;
end;
....
if TryCalcProportionAsAmount(блаблабла, Variable) then
Do(Variable);
← →
12 © (2010-12-23 11:21) [39]Raise; - ну тут варианты..
← →
han_malign (2010-12-23 12:35) [40]
> Не всё так просто
- с currency - просто(ε=0.0001)
>> А деление проверяется на зеро заранее.
> ты не погорячился?
- подразумевался пост 12 © (23.12.10 10:20) [30], и тут надо исходить из вероятности возникновения ситуации...
Если это исключительная, крайне редкая ситуация - то лишнее ветвление(не убирающее необходимости защищенной секции) - избыточно.
Но учитывая:
> {Здесь некотовый код, определены значения переменных rlBase, rlMulti, rlBaseDM, rlMultiDM. Кстати, значение rlBaseDM, rlMultiDM порой бывают равны нулю}
- ситуация вполне нормальная, и ветвление обосновано, т.к. нормальные входные данные не должны порождать исключение(которое дает значительное пенальти производительности)...
← →
Abcdef123 (2010-12-24 05:54) [41]To [40]: Красиво написано, но не поняла, вы за использование использование проверки на нуль или за использование except?
← →
Ega23 © (2010-12-24 06:20) [42]
> вы за использование использование проверки на нуль или
> за использование except?
Дурная постановка вопроса.
← →
Abcdef123 (2011-01-18 08:50) [43]Здравствуйте, Мастера.
Докладываю - наконец-то у клиента всё протестировали, но, ничего не помогло. Проблема существует.
А вот, что произошло на моем компе! Как я писала, что у меня на компе программа работает нормально.
Но, как только я протестировала идею [19], у меня вылетает такая же ошибка! Хотя предложение использовать asm FINIT end; должно бы наоборот - помочь!
Я прошла пошагово, и нашла, что когда
в функции идет деление на ноль, то программа не идет на except, а присваивает результату вот такое больше разрядное значение.
Если я добавлю перед применением формулы проверку на ноль, то ошибки нет.
В общем, чтобы уж точно было понятно привожу описываемые варинты: работаютщие:
function CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount : Currency) : Currency;
begin
try
result:= rlAmount * (rlSubTotal / rlTotal);
except
result:= 0;
end;
end
function CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount : Currency) : Currency;
begin
asm FINIT end;
try
if rlTotal <> 0 then
result:= rlAmount * (rlSubTotal / rlTotal)
else
result:= 0;
except
result:= 0;
end;
end
А ЭТО НЕРАБОТАЮЩИЙ:
function CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount : Currency) : Currency;
begin
asm FINIT end;
try
result:= rlAmount * (rlSubTotal / rlTotal);
except
result:= 0;
end;
end
На моем компе я проверяю с моим принтером. То есть всё также много вопросов - всё те же.
Прошу прокомментировать.
← →
12 © (2011-01-18 09:48) [44]
> когда
> в функции идет деление на ноль, то программа не идет на
> except, а присваивает результату вот такое больше разрядное
> значение.
Вероятно, там не 0, а несколько больше(меньше).
function CalcProportionAsAmount(rlTotal, rlSubTotal, rlAmount : Currency) : Currency;
const
Eps = 0.0001;
begin
try
if (rlTotal > Eps) then
result:= rlAmount * (rlSubTotal / rlTotal)
else
result:= 0;
except
result:= 0;
end;
end;
Григорьев Антон, "Невероятные особенности вещественных чисел" , как-то так, гуглите, короче
← →
Amoeba_ (2011-01-18 11:47) [45]
> Григорьев Антон, "Невероятные особенности вещественных чисел"
> , как-то так, гуглите, короче
Неочевидные особенности вещественных чисел
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374
← →
12 © (2011-01-18 15:51) [46]да-да
var
R:Single;
begin
R:=0.1;
if R=0.1 then
Label1.Caption:="Равно" else
Label1.Caption:="Не равно"
end;
При нажатии кнопки мы увидим надпись «Не равно». На первый взгляд это кажется абсурдом.
(с) Антон Григорьев
из этой же серии, имхо
← →
12 © (2011-01-18 16:21) [47]еще раз тему перечитал - тогда так: Компьютер портит.
Без компьютера же программа не лажает?!
Вот.. :)
А чтоб программа не лажала - ее надо отлаживать (с)
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.04.24;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.004 c