Исключения с плавающей точкой - ошибка gcc? - PullRequest
4 голосов
/ 14 июня 2011

Рассмотрим следующий код:

#include <fenv.h>
#include <stdio.h>
int main()
{
    #pragma STDC FENV_ACCESS ON
    1.0/0.0;
    printf("%x\n", fetestexcept(FE_ALL_EXCEPT));
}

Я ожидал бы, что он напечатает ненулевое значение, соответствующее FE_DIVBYZERO, но он напечатает 0. Изменение второй строки main на double x = 1.0/0.0; дает ожидаемое поведение. Это разрешено или это ошибка?

Редактировать: Поначалу может показаться, что в большинстве реальных программ операции, которые могут вызывать исключения fenv, не могут быть оптимизированы, поэтому можно безопасно выполнять большие вычисления и проверка в конце, произошло ли переполнение, деление на ноль и т. д. Тем не менее, все становится запутанным, и возникает реальная проблема, когда вы рассматриваете встраивание и оптимизацию. Если бы такая функция была встроена в ситуации, когда она всегда заканчивалась делением на ноль из-за постоянных аргументов, gcc мог бы получить действительно умных и оптимизировать всю встроенную функцию по существу до return INFINITY;, не вызывая никаких исключений.

Ответы [ 5 ]

6 голосов
/ 14 июня 2011

Это ожидаемое поведение. gcc не оценивает выражение, потому что впоследствии оно не имеет к нему никакого отношения.

Если вы компилируете с "-Wall", он предупреждает вас, что это утверждение не имеет никакого эффекта, и игнорирует прагматическое утверждение.

GCC не полностью совместим с C99. Для получения дополнительной информации см .: http://gcc.gnu.org/c99status.html

По вопросу реализации этого поведения см .: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20785

2 голосов
/ 14 июня 2011

Компиляция с -Wall на gcc 4.6.0 говорит:

f.c:5:0: warning: ignoring #pragma FENV_ACCESS ON [-Wunknown-pragmas]

По данным информационных страниц GCC :

* `The default state for the `FENV_ACCESS' pragma (C99 7.6.1).'

 This pragma is not implemented, but the default is to "off" unless
 `-frounding-math' is used in which case it is "on".

К сожалению, -frounding-math не оказывает никакого влияния на вашу программу.

Возможно, ошибка компилятора; Я бы спросил в одном из списков рассылки GCC.

2 голосов
/ 14 июня 2011

Это что-то серое. Строгое прочтение раздела стандарта с плавающей запятой может легко привести к выводу, что это ошибка. Я подозреваю, что сопровождающие GCC не согласятся с этим чтением, однако.

В этом отношении я не уверен, что GCC даже утверждает, что понимает прагму FENV_ACCESS. Конечно, более ранние версии не сделали.

0 голосов
/ 14 июня 2011

Я думаю, что выражение оптимизируется в первом случае, но не во втором.Я могу воспроизвести ваши результаты с помощью gcc 4.2 с gcc -O0, но если перейти к gcc -O3, я получу 0 в обоих случаях.

0 голосов
/ 14 июня 2011

Возможно, ваш компилятор оптимизировал исходную версию. Признавая, что эти две константы не «используются» ни в каком нетривиальном смысле, они могут даже не существовать в скомпилированном двоичном файле.

Второй пример меняет это, фактически назначая операцию переменной.

...