float get_NaN(){
float ret=0;
unsigned char *p;
p=(unsigned char*)(&ret);
p[0]=0xff;
p[1]=0xff;
p[2]=0xff;
p[3]=0xff;
return ret;
}
int work(){
int ret=0;
float a1=0;
float a2;
a1=get_NaN();
a2=a1;
if(a1==a2) ret=1;
return ret;
}
int work1(){
int ret=0;
float a1=0;
a1=get_NaN();
if(a1<0.1) ret=1;
return ret;
}
int work2(){
int ret=0;
float a1=0;
float a2=0.1;
a1=get_NaN();
if(a1>a2) ret=1;
return ret;
}
//---------------------------------------------------------------------------#pragma hdrstop
//---------------------------------------------------------------------------#pragma argsused
int main(int argc, char* argv[]){
int ret;
ret=work();
ret=work1();
ret=work2();
return ret;
}
//---------------------------------------------------------------------------
Этот пример транслируется, но при запуске падает с диагностикой:
---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class EInvalidOp with message 'Invalid floating point operation'. Process stopped. Use Step or Run to continue.
Падает он на строке return ret; в функции get_NaN(). Причем только при втором проходе (то есть при вызове этой функции из work1())
Вопросы:
1. Как вообще по стандарту должно обрабатываться значение NaN?
2. Почему пример падает только при втором проходе?
Здравствуйте, Аноним, Вы писали:
А>float get_NaN(){
Вообще-то nan(), nanf() есть в стандартной библиотеке.
А>Project Project1.exe raised exception class EInvalidOp with message 'Invalid floating point operation'. Process stopped. Use Step or Run to continue.
А>Падает он на строке return ret; в функции get_NaN(). Причем только при втором проходе (то есть при вызове этой функции из work1())
А>2. Почему пример падает только при втором проходе?
Попробуйте отделить work() — work2() в один исходный файл, а main() в другой. Это уберёт все оптимизации кода на основании знания содержимого функций. Если не поможет — смотрите в ассемблере, во что get_NaN() компилируется в каком случае.
The God is real, unless declared integer.
Re[2]: обработка NaN в BCB60
От:
Аноним
Дата:
26.08.10 12:53
Оценка:
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, Аноним, Вы писали:
А>>float get_NaN(){
N>Вообще-то nan(), nanf() есть в стандартной библиотеке.
[C++ Error] Unit1.cpp(8): E2268 Call to undefined function 'nan'
А>>Project Project1.exe raised exception class EInvalidOp with message 'Invalid floating point operation'. Process stopped. Use Step or Run to continue.
А>>Падает он на строке return ret; в функции get_NaN(). Причем только при втором проходе (то есть при вызове этой функции из work1())
А>>2. Почему пример падает только при втором проходе?
N>Попробуйте отделить work() — work2() в один исходный файл, а main() в другой. Это уберёт все оптимизации кода на основании знания содержимого функций. Если не поможет — смотрите в ассемблере, во что get_NaN() компилируется в каком случае.
Такое впечатление, что обработка NaN в BCB60 приводит к нестабильности программы. И эта нестабильность проявляется сильно после возникновения.
Здравствуйте, Аноним, Вы писали:
N>>Вообще-то nan(), nanf() есть в стандартной библиотеке. А>[C++ Error] Unit1.cpp(8): E2268 Call to undefined function 'nan'
Наверно, надо подключить математическую библиотеку?
N>>Попробуйте отделить work() — work2() в один исходный файл, а main() в другой. Это уберёт все оптимизации кода на основании знания содержимого функций. Если не поможет — смотрите в ассемблере, во что get_NaN() компилируется в каком случае. А>Такое впечатление, что обработка NaN в BCB60 приводит к нестабильности программы. И эта нестабильность проявляется сильно после возникновения.
Это очень невнятное впечатление. Попробуйте между вызовами разных work() снять и вывести в лог настройки режима плавающей точки (функция fegetenv()).
А>1. Как вообще по стандарту должно обрабатываться значение NaN? А>2. Почему пример падает только при втором проходе?
у борланда вообще дурацкая привычка по-умолчанию включать floating point exceptions. В результате даже вполне корректные манипуляции с бесконечностями могут падать. Хотя код не смотрел, может в этом случае они и не корректные