Как отловить исключение целочисленного деления на ноль в языке Си? - PullRequest
4 голосов
/ 24 июня 2010

Известно, как поймать исключение деления на ноль с плавающей запятой с использованием

signal(SIGFPE, handler)

, но он не улавливает проблему деления на ноль, даже если я установил управляющее слово с

_control87(0, _MCW_EM ); (MS VC 2010)

SubQuestion_1: Как отловить целочисленное деление на ноль в C-программе в Windows без использования SEH EXCEPTION_INT_DIVIDE_BY_ZERO? (В Unix / Linux это можно сделать с использованием стандартного techinque signal / SIGFPE)

EDIT: сигнал является подходом обработки сигналов ANSI C.
_control87 - это стандартная функция Windows для установки управляющего слова с плавающей точкой.

Аналогичный вопрос: Как обрабатывать все ошибки, включая внутренние ошибки библиотеки C, равномерно

ПРИМЕЧАНИЕ (из ИСО / МЭК 9899: Приложение H.2.2 TC2):

"Целочисленные типы C со знаком int, long int, long long int и соответствующие им беззнаковые типы совместимы с LIA-1. ... Целочисленные типы C без знака являются «по модулю» в смысле LIA-1 в том смысле, что результаты переполнения или выхода за пределы автоматически скрываются. Реализация, которая определяет целочисленные типы со знаком как также по модулю, не должна обнаруживать переполнение целых чисел, и в этом случае должно быть обнаружено только целочисленное деление на ноль. ? ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ:

Для Windows: выдает исключение SEH. Так что это можно поймать с помощью __try __except. В качестве возможного решения можно использовать трансляцию SEH для обработки исключений SEH и преобразования их в вызов необходимой функции. Это не «естественный» способ, но кажется, что это единственный путь.

Для Unix: он может быть перехвачен с помощью сигнала / SIGFPE. Или проверьте вики для решения FPE_INTDIV (http://rosettacode.org/wiki/Detect_division_by_zero#C).

Поскольку GMan был прав насчет "неопределенного поведения", я выбираю его ответ как правильный.

Примечание. Интересно проверить массив VC \ crt \ src \ winxfltr.c: _XcptActTab:)

Ответы [ 2 ]

18 голосов
/ 24 июня 2010

Деление на ноль приводит к неопределенному поведению, нет никакой конструкции языка C, которая могла бы с этим что-либо делать. Лучше всего не делить на ноль, проверяя знаменатель.

Если вы хотите «поймать» (заметьте, C не имеет исключений) эту ошибку, она будет зависеть от вашего компилятора и ОС, которых вы не указали. Кстати, _control87 имеет отношение только к операциям с плавающей точкой, и не имеет ничего общего с целочисленными операциями.

0 голосов
/ 24 июня 2010

Проверьте, что вы делите против ...?

// if below = 0 then do not divide, just put answer as zero

if (below == 0) {
  result = 0;
} else {
  result = above/below;
}
...