Как бороться ?
От: flyker Россия  
Дата: 20.03.02 13:08
Оценка:
Кто-нибудь сталкивался с эксепшонами типа C0000090 ?
Как с этим бороться ? Вылезает на ровном месте, причем совершенно непонятно почему.
Пробовал вставлять вызов _control87(_MCW_EM, _MCW_EM) но это не помогает, каким то совершенно непонятным образом флаги сбрасываются в совершенно дикий вид.
В нормальном состоянии флаги такие ControlWord=FFFF027F StatusWord=FFFF0000 TagWord=FFFFFFFF (где бы еще нарыть что это означает.... )
При ошибке флаги CTW=FFFF1370 STW=FFFFFDA1 TGW=FFFFBFFF
Прямо беда.
Все гениальное — просто
Re: Как бороться ?
От: GromRom Россия  
Дата: 20.03.02 14:10
Оценка:
Здравствуйте flyker, Вы писали:

Вставь кусочек кода, где(по-твоему) возникает эксепшен
Девиз настоящих студентов: Не боись — ПРОРВЁМСЯ
Re[2]: Как бороться ?
От: flyker Россия  
Дата: 20.03.02 14:38
Оценка:
GR>Вставь кусочек кода, где(по-твоему) возникает эксепшен

Вот исходник:

char* Intl::PrintMoney(double dbl, char *str, WORD w)
{
if( dbl < 0 && dbl > -MoneyEps() ) dbl = 0.0;
return PrintFloat(dbl, str, bCurrDigits, w);
}

Вот он-же в дебаггере:

0FFB7441 push ebp
0FFB7442 mov ebp,esp
0FFB7444 push ecx
0FFB7445 push ecx
0FFB7446 mov dword ptr [ebp-8],0CCCCCCCCh
0FFB744D mov dword ptr [ebp-4],0CCCCCCCCh
0FFB7454 mov dword ptr [ebp-8],edx
0FFB7457 mov dword ptr [ebp-4],ecx
0FFB745A fld qword ptr [dbl]
0FFB745D fcomp qword ptr [__real@8@00000000000000000000 (0ffc64e0)] Исключение возникает по этому адресу
0FFB7463 fnstsw ax
0FFB7465 sahf
0FFB7466 jae Intl::PrintMoney+3Ch (0ffb747d)
0FFB7468 fld dword ptr [Intl::moneyEps (0ffd39ac)]
0FFB746E fchs
0FFB7470 fcomp qword ptr [dbl]
0FFB7473 fnstsw ax
0FFB7475 sahf
0FFB7476 jae Intl::PrintMoney+3Ch (0ffb747d)
Все гениальное — просто
Re[3]: Как бороться ?
От: Sergey Россия  
Дата: 20.03.02 14:46
Оценка:
Здравствуйте flyker, Вы писали:


GR>>Вставь кусочек кода, где(по-твоему) возникает эксепшен


F>Вот исходник:


F>char* Intl::PrintMoney(double dbl, char *str, WORD w)

F>{
F> if( dbl < 0 && dbl > -MoneyEps() ) dbl = 0.0;
F> return PrintFloat(dbl, str, bCurrDigits, w);
F>}

F>Вот он-же в дебаггере:


F>0FFB7441 push ebp

F>0FFB7442 mov ebp,esp
F>0FFB7444 push ecx
F>0FFB7445 push ecx
F>0FFB7446 mov dword ptr [ebp-8],0CCCCCCCCh
F>0FFB744D mov dword ptr [ebp-4],0CCCCCCCCh
F>0FFB7454 mov dword ptr [ebp-8],edx
F>0FFB7457 mov dword ptr [ebp-4],ecx
F>0FFB745A fld qword ptr [dbl]
F>0FFB745D fcomp qword ptr [__real@8@00000000000000000000 (0ffc64e0)] Исключение возникает по этому адресу
F>0FFB7463 fnstsw ax
F>0FFB7465 sahf
F>0FFB7466 jae Intl::PrintMoney+3Ch (0ffb747d)
F>0FFB7468 fld dword ptr [Intl::moneyEps (0ffd39ac)]
F>0FFB746E fchs
F>0FFB7470 fcomp qword ptr [dbl]
F>0FFB7473 fnstsw ax
F>0FFB7475 sahf
F>0FFB7476 jae Intl::PrintMoney+3Ch (0ffb747d)

dbl какой перед сравнением? Наверное, NaN какой-нибудь, да еще и signaling NaN небось? Вставь перед сравнением проверку _finite(dbl) или хотя бы _isnan(dbl).
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[3]: Как бороться ?
От: GromRom Россия  
Дата: 20.03.02 14:53
Оценка:
Здравствуйте flyker, Вы писали:

GR>>Вставь кусочек кода, где(по-твоему) возникает эксепшен


F>Вот исходник:


F>char* Intl::PrintMoney(double dbl, char *str, WORD w)

F>{
F> if( dbl < 0 && dbl > -MoneyEps() ) dbl = 0.0;
F> return PrintFloat(dbl, str, bCurrDigits, w);
F>}

Во-первых всё то, что сказал Sergey
а во-вторых сравнение лучше делать так:
if(dbl < 0.0000001){...} //Вместо 0.0000001 можно ставить любую другую точность, которая тебя устраивает

незабудь и возвращаемое MoneyEps() проверить на бесконечность и прочие бяки

я больше причин не вижу
Девиз настоящих студентов: Не боись — ПРОРВЁМСЯ
Re[4]: Как бороться ?
От: Аноним  
Дата: 20.03.02 15:14
Оценка:
Здравствуйте GromRom, Вы писали:

GR>Здравствуйте flyker, Вы писали:


GR>>>Вставь кусочек кода, где(по-твоему) возникает эксепшен


F>>Вот исходник:


F>>char* Intl::PrintMoney(double dbl, char *str, WORD w)

F>>{
F>> if( dbl < 0 && dbl > -MoneyEps() ) dbl = 0.0;
F>> return PrintFloat(dbl, str, bCurrDigits, w);
F>>}

GR>Во-первых всё то, что сказал Sergey

GR>а во-вторых сравнение лучше делать так:
GR>if(dbl < 0.0000001){...} //Вместо 0.0000001 можно ставить любую другую точность, которая тебя устраивает

GR>незабудь и возвращаемое MoneyEps() проверить на бесконечность и прочие бяки


Ну MoneyEps() возвращает константу, это так к слову...
Понимаете в чем дело, я не могу везде в коде понатыкать эти проверки,
таких мест слишком много. Хотелось бы иметь универсальный метод, при котором
такие исключение вообще бы никогда не возникали.
Собственно функция _control87 вроде бы именно этому и служит.
С ее помощью по идее можно отключить все Float Exceptions.
Re[5]: Как бороться ?
От: Sergey Россия  
Дата: 20.03.02 15:26
Оценка:
Здравствуйте Аноним, Вы писали:

А>Здравствуйте GromRom, Вы писали:


GR>>Здравствуйте flyker, Вы писали:


GR>>>>Вставь кусочек кода, где(по-твоему) возникает эксепшен


F>>>Вот исходник:


F>>>char* Intl::PrintMoney(double dbl, char *str, WORD w)

F>>>{
F>>> if( dbl < 0 && dbl > -MoneyEps() ) dbl = 0.0;
F>>> return PrintFloat(dbl, str, bCurrDigits, w);
F>>>}

GR>>Во-первых всё то, что сказал Sergey

GR>>а во-вторых сравнение лучше делать так:
GR>>if(dbl < 0.0000001){...} //Вместо 0.0000001 можно ставить любую другую точность, которая тебя устраивает

GR>>незабудь и возвращаемое MoneyEps() проверить на бесконечность и прочие бяки


А>Ну MoneyEps() возвращает константу, это так к слову...

А>Понимаете в чем дело, я не могу везде в коде понатыкать эти проверки,
А>таких мест слишком много. Хотелось бы иметь универсальный метод, при котором
А>такие исключение вообще бы никогда не возникали.
А>Собственно функция _control87 вроде бы именно этому и служит.
А>С ее помощью по идее можно отключить все Float Exceptions.

Не, не все. signaling NaN на то и signaling, что фиг отключишь. А кроме того, подумай — тебя ж бугалтеры (или кто там у тебя заказчики) не поймут, если у тебя вместо денег всякие #INF печататься будут. Представь себе — бесконечно много денег А проверять надо, когда на 0 делишь ну и входные данные, при печати это делать поздно. Опять же, результат сравнения числа с quit NaN зависит от порядка операторов — есть где багов половить, а? Так что ексепшны отключать зачастую себе дороже.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[6]: Как бороться ?
От: Аноним  
Дата: 20.03.02 15:58
Оценка:
Здравствуйте Sergey, Вы писали:

S>Здравствуйте Аноним, Вы писали:


А>>Здравствуйте GromRom, Вы писали:


GR>>>Здравствуйте flyker, Вы писали:


GR>>>>>Вставь кусочек кода, где(по-твоему) возникает эксепшен


F>>>>Вот исходник:


F>>>>char* Intl::PrintMoney(double dbl, char *str, WORD w)

F>>>>{
F>>>> if( dbl < 0 && dbl > -MoneyEps() ) dbl = 0.0;
F>>>> return PrintFloat(dbl, str, bCurrDigits, w);
F>>>>}

GR>>>Во-первых всё то, что сказал Sergey

GR>>>а во-вторых сравнение лучше делать так:
GR>>>if(dbl < 0.0000001){...} //Вместо 0.0000001 можно ставить любую другую точность, которая тебя устраивает

GR>>>незабудь и возвращаемое MoneyEps() проверить на бесконечность и прочие бяки


А>>Ну MoneyEps() возвращает константу, это так к слову...

А>>Понимаете в чем дело, я не могу везде в коде понатыкать эти проверки,
А>>таких мест слишком много. Хотелось бы иметь универсальный метод, при котором
А>>такие исключение вообще бы никогда не возникали.
А>>Собственно функция _control87 вроде бы именно этому и служит.
А>>С ее помощью по идее можно отключить все Float Exceptions.

S> Не, не все. signaling NaN на то и signaling, что фиг отключишь. А кроме того, подумай — тебя ж бугалтеры (или кто там у тебя заказчики) не поймут, если у тебя вместо денег всякие #INF печататься будут. Представь себе — бесконечно много денег :)) А проверять надо, когда на 0 делишь ну и входные данные, при печати это делать поздно. Опять же, результат сравнения числа с quit NaN зависит от порядка операторов — есть где багов половить, а? Так что ексепшны отключать зачастую себе дороже.


В общем понятно, придется ловить багу :( не отвертется
Спасибо :user:
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.