Почему целочисленное деление на ноль приводит к исключению с плавающей запятой?

Деление на ноль в программе C приводит к аварийному завершению с сообщением об ошибке Floating point exception (core dumped). Это неудивительно для деления с плавающей запятой, но почему он говорит об этом, когда происходит целочисленное деление на ноль? Действительно ли целочисленное деление использует FPU под капотом?

(Кстати, это все в Linux под x86.)


person Taymon    schedule 04.06.2013    source источник
comment
Стоит отметить, что другие операционные системы, не относящиеся к POSIX (например, Windows) и оборудование x86, сообщают о разных исключениях для целочисленного деления и деления с плавающей запятой на ноль.   -  person Crashworks    schedule 03.06.2016
comment
Связано: На каких платформах Целочисленное деление на ноль вызывает исключение с плавающей запятой?. TL: DR: POSIX требует, чтобы это был SIGFPE, если сигнал вообще есть.   -  person Peter Cordes    schedule 23.09.2017


Ответы (4)


Действительно ли целочисленное деление использует FPU под капотом?

Нет, Linux и в этом случае просто генерирует SIGFPE (это устаревшее имя, использование которого теперь расширено). Действительно, спецификация единой Unix определяет SIGFPE как " Ошибочные арифметические операции ".

person Oliver Charlesworth    schedule 04.06.2013

man signal упоминает:

Целочисленное деление на ноль дает неопределенный результат. На некоторых архитектурах он генерирует сигнал SIGFPE. (Также деление самого отрицательного целого числа на -1 может привести к появлению SIGFPE.)

person millimoose    schedule 04.06.2013

Я предполагаю, что историческое объяснение этому будет заключаться в том, что исходное оборудование Unix не генерировало ловушку при целочисленном делении на ноль, поэтому имя SIGFPE имело смысл. (Программисты сборки PDP, подтвердите?) Затем, позже, когда система была перенесена (или, в случае Linux, переопределена) на оборудование с ловушкой целочисленного деления на ноль, не было сочтено целесообразным добавлять новый номер сигнала, поэтому старый приобрел новое значение и теперь имеет немного сбивающее с толку название.

person Community    schedule 04.06.2013
comment
Кажется, вы правы: согласно этой ссылке, Инструкция DIV просто устанавливает флаги C и V на деление на ноль, а V - только если результат не помещается в регистр назначения. OTOH, согласно этой странице FP11 - более новый FPU PDP-11 - действительно поддерживал треппинг. Так что действительно изначально не было необходимости в имени сигнала ошибки целочисленного деления. - person Ruslan; 31.03.2018

Для этого может быть много разных причин, связанных с реализацией.

Например, блок FPU на платформе x86 поддерживает форматы как с плавающей запятой, так и целочисленные для чтения аргументов и записи результатов. Когда сама платформа была 16-битной, некоторые компиляторы использовали FPU для выполнения деления с 32-битными целочисленными операндами (поскольку нет потери точности для 32-битных данных). При таких обстоятельствах не было бы ничего необычного в получении подлинной ошибки FPU из-за недопустимого 32-битного целочисленного деления.

person AnT    schedule 05.06.2013
comment
Исключения FP обычно маскируются, поэтому вы просто получаете результат NaN или +/- Inf вместо исключения. Интересно, началось ли SIGFPE для соглашения / традиции об исключениях целочисленного деления до x86? Unix не мог быть должным образом перенесен на x86 до 386 (защищенный режим), но я думаю, что некоторые Unix-подобные среды без реальной защиты памяти существовали. - person Peter Cordes; 12.10.2016
comment
@PeterCordes, похоже, ELKS по крайней мере пытался портировать Linux не только на 286, но даже на 8086. Я даже запускал его на машине 286. Я полагаю, что UNIX тоже можно портировать. - person Ruslan; 31.03.2018