Ответ 1
Я не уверен, как сложилась текущая ситуация, но в настоящее время поддержка обнаружения исключений в FP сильно отличается от целочисленной. Обычно целочисленное деление в ловушку. POSIX требует, чтобы он поднял SIGFPE
, если вообще вызывает исключение.
Тем не менее, вы можете разобраться, что это был за SIGFPE, чтобы увидеть, что это на самом деле исключение деления. (Не обязательно делить на ноль, хотя: 2 дополняют ловушки деления INT_MIN
/-1
, а x86 div
и idiv
также ловят, когда частное деления 64b/32b не вписывается в выходной регистр 32b. Но это не так для AArch64 с использованием sdiv
.)
В руководстве glibc объясняется, что системы BSD и GNU доставляют дополнительный аргумент обработчику сигнала для SIGFPE
, который будет FPE_INTDIV_TRAP
для деления на ноль. POSIX документирует FPE_INTDIV_TRAP
как возможное значение для поля siginfo_t
int si_code
в системах, где siginfo_t
включает этот элемент.
IDK, если Windows поставляет другое исключение в первую очередь, или если она объединяет вещи в разные разновидности одного и того же арифметического исключения, как в Unix. Если это так, обработчик по умолчанию декодирует дополнительную информацию, чтобы сообщить вам, какое это было исключение.
POSIX и Windows используют фразу "деление на ноль", чтобы охватить все исключения целочисленного деления, так что, очевидно, это обычное сокращение. Для людей, которые знают о проблеме INT_MIN / -1 (с 2 дополнениями), фразу "деление на ноль" можно считать синонимом исключения деления. Фраза сразу указывает на общий случай для людей, которые не знают, почему целочисленное деление может быть проблемой.
Семантика исключений FP
Исключения FP по умолчанию маскируются для процессов пользовательского пространства в большинстве операционных систем /ABI C.
Это имеет смысл, поскольку плавающая точка IEEE может представлять бесконечности и имеет NaN, чтобы распространять ошибку на все будущие вычисления с использованием значения.
0.0/0.0
=>NaN
- Если
x
конечно:x/0.0
=>+/-Inf
со знаком x
Это даже позволяет таким вещам давать ощутимый результат, когда исключения маскируются:
double x = 0.0;
double y = 1.0/x; // y = +Inf
double z = 1.0/y; // z = 1/Inf = 0.0, no FP exception
Обнаружение ошибок FP и целых чисел
Способ обнаружения ошибок в FP очень хорош: когда маскируются исключения, они устанавливают флаг в регистре состояния FP вместо перехвата. (например, x86 MXCSR для инструкций SSE). Флаг остается установленным до тех пор, пока не будет сброшен вручную, поэтому вы можете проверить один раз (например, после цикла), чтобы увидеть, какие исключения произошли, а не где они произошли.
Были предложения о том, чтобы иметь аналогичные "липкие" флаги целочисленного переполнения, чтобы записывать, происходило ли переполнение в любой точке во время последовательности вычислений. Позволять маскировать исключения целочисленного деления было бы хорошо в некоторых случаях, но опасно в других случаях (например, при вычислении адреса, вы должны ловушку вместо того, чтобы потенциально сохранять в поддельном месте).
На x86, однако, обнаружение переполнения целого числа во время последовательности вычислений требует установки условной ветки после каждого из них, поскольку флаги просто перезаписываются. MIPS имеет инструкцию add
, которая перехватывает переполнение со знаком, и инструкцию без знака, которая никогда не перехватывает. Таким образом, обнаружение и обработка целочисленных исключений намного менее стандартизированы.
Целочисленное деление не позволяет выводить результаты NaN или Inf, так что имеет смысл работать таким образом.
Любой целочисленный битовый шаблон, полученный целочисленным делением, будет неправильным, поскольку он будет представлять конкретное конечное значение.
Однако в x86 преобразование значения с плавающей запятой вне целого числа в целое число с помощью cvtsd2si
или любой подобной инструкции преобразования создает значение "целочисленное неопределенное", если исключение "недопустимая плавающая точка" замаскировано, Значение равно нулю, кроме знакового бита. то есть INT_MIN
.
(См. руководства Intel, ссылки в вики-теге x86.