Деление на ноль не вызывает SIGFPE

У меня есть небольшая программа, выполняющая деление с плавающей запятой на ноль, поэтому я ожидаю SIGFPE.

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

void signal_handler (int signo) {
    if(signo == SIGFPE) {
      std::cout << "Caught FPE\n";
    }
}

int main (void) {
  signal(SIGFPE,(*signal_handler));

  double b = 1.0;
  double c = 0.0;
  double d = b/c;
  std::cout << "d = "<< d << std::endl;
  return 0;
}

Собственно, я получил следующий вывод:

d = inf

gcc версии 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

Что мне делать, чтобы выкинуть SIGFPE в этом случае? От каких факторов зависит поведение FP (флаги компилятора/тип процессора и т.д.)?

Спасибо


person Community    schedule 01.09.2011    source источник
comment
Это должно быть довольно стандартно, если у вас есть поплавки IEEE.   -  person Ingo    schedule 01.09.2011


Ответы (3)


Для чисел с плавающей запятой вы можете изменить это поведение, настроив управляющее слово FPU. Посмотрите здесь

person Oleg    schedule 01.09.2011
comment
Я знаю о управляющем слове FPU. Это может быть установлено с помощью _controlfp() на платформе MS. Существует ли эквивалент POSIX для этой функции? - person ; 01.09.2011
comment
@Yuri: Посмотрите, определяет ли ваш стандартный включаемый файл <fenv.h> fesettrapenable. Это нестандартно, но широко доступно. В Linux используйте feenableexcept -- но вам нужно #define _GNU_SOURCE перед #include <fenv.h>. - person David Hammen; 01.09.2011
comment
@ Юрий С. Черкасов Это в fpu_control.h. Проверьте здесь: christian-seiler.de/projekte/fpmath - person Oleg; 01.09.2011
comment
@Oleg: fenv.h обычно лучше. fpu_control.h отсутствует на всех платформах, не поддерживающих glibc: MacOS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 11 2010-11, Cygwin, mingw, Interix 3.5, БеОС - person David Hammen; 01.09.2011
comment
@ Дэвид Хаммен, согласен. Но автор темы использует Ubuntu, так что с ним все в порядке. (опять же - договоритесь о кроссплатформенности и т.д.) - person Oleg; 02.09.2011
comment
Печально то, что нет стандартного способа сделать это. Еще печальнее то, что поведение по умолчанию (по крайней мере, на каждой машине, которую я использовал) — разрешить деление на ноль и т. д. Эти Infs и NaN почти всегда являются результатом ошибки программирования, распространяются как кролики по данным, медленные вычисления на несколько порядков, и очень трудно отследить первопричину. - person David Hammen; 02.09.2011

Вы получите сигнал, только если выполните целочисленное деление на ноль. Для чисел с плавающей запятой деление на ноль четко определено.

На самом деле это довольно хорошо объясняется в статье Википедии.

person Motti    schedule 01.09.2011
comment
Я не придираюсь к вашему ответу, просто придираюсь к этой бессмыслице в стандарте IEEE. Подумайте, какой в ​​этом смысл: вы получите исключение с плавающей запятой, если выполните целочисленное деление на ноль. По умолчанию вы не получаете исключение с плавающей запятой, если выполняете деление с плавающей запятой на ноль. Людям, зарабатывающим на жизнь численными вычислениями, обычно не нравится, что это поведение по умолчанию. Хуже того, нет стандарта для получения желаемого поведения. Деление на ноль и т. д. почти всегда являются признаком того, что что-то пошло не так. - person David Hammen; 01.09.2011
comment
Чтение исходного кода превосходит википедию: 754r.ucbtest.org/standards/754.pdf: 7.2: Если делитель равен нулю, а делимое является конечным числом, отличным от нуля, то должно быть указано исключение деления на ноль. Результатом, когда trap не происходит, должно быть правильно подписанное INFINITY (6.3). И глава 8 говорит нам, что пользователь должен иметь возможность указать обработчик trap, который вызывается при возникновении любого из исключений в главе 7. - person Nordic Mainframe; 01.09.2011
comment
Это интересно, но цель состоит в том, чтобы отловить такие ситуации, потому что деление на ноль в моем контексте является недопустимой операцией. - person ; 01.09.2011
comment
@Luther: Ну да, но в нем не указано, как обрабатываются ловушки и исключения, и, в частности, им не нужно сопоставлять сигналы в стиле ОС и / или C. - person janneb; 01.09.2011
comment
@janneb: В нем также говорится, что пользователь должен иметь возможность указать обработчик ловушек, а не должен. Использование должен, а не должен вполне преднамеренно. Перехват этих исключений является дополнительной функцией. - person David Hammen; 01.09.2011

Вы не получаете сигнал, потому что поведение по умолчанию на большинстве машин состоит в том, чтобы загрязнять ваши данные NaN (не число) и бесконечностями. Вы должны включить исключения с плавающей запятой, и то, как вы это сделаете, зависит от машины. Посмотрите системную шапку fenv.h, если она у вас есть. Функция fesettrapenable позволяет перехватывать исключения с плавающей запятой на многих машинах.

К сожалению, нет стандартной функции для включения обработки исключений с плавающей запятой.

person David Hammen    schedule 01.09.2011