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

Вниз

Принтер "портит" выполнение программы?   Найти похожие ветки 

 
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 - просто(&#949;=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;
Скачать: CL | DM;

Наверх




Память: 0.6 MB
Время: 0.014 c
15-1294649384
tat'yanka
2011-01-10 11:49
2011.04.24
Дифрагментация дискового пространства


1-1252963791
Ruzzz
2009-09-15 01:29
2011.04.24
Результат в регистр AX, как работает компилятор?


15-1294522195
Юрий
2011-01-09 00:29
2011.04.24
С днем рождения ! 9 января 2011 воскресенье


15-1294176598
Юрий
2011-01-05 00:29
2011.04.24
С днем рождения ! 5 января 2011 среда


2-1295537929
Айнур
2011-01-20 18:38
2011.04.24
Вопрос по Edit