Любое число, деленное на 0 в C, подвергается ли оно ошибке сегментации?

int main()
{
    int x = 5, y = 0;
    int z = x / y;
    return 0;
}

Я знаю, что это связано с неопределенным поведением, но означает ли это ошибку сегментации? И как процессор обрабатывает деление на 0?

Когда я запускаю это, я получаю исключение с плавающей запятой (ядро сбрасывается).


person Ayushi    schedule 04.07.2018    source источник
comment
Исключение с плавающей запятой не является ошибкой сегментации.   -  person JJJ    schedule 04.07.2018
comment
Если вы спрашиваете о влиянии на конкретную систему, пожалуйста, отредактируйте свой вопрос и сообщите нам, какая система.   -  person user694733    schedule 04.07.2018
comment
ЦП обрабатывает это, выбрасывая аппаратное исключение. И все, это не имеет никакого отношения ни к языку Си, ни к ОС.   -  person Lundin    schedule 04.07.2018
comment
бессмысленный вопрос UB, см. значение undefined. Что именно произойдет, зависит от вашей машины и среды. Кстати, деление на 0 может быть четко определено для типов с плавающей запятой, если используется формат IEEE-754.   -  person    schedule 04.07.2018


Ответы (2)


Если поведение не определено, это означает, что нет определения тому, что происходит. Таким образом, постановка вопроса «означает ли это ошибку сегментации» означает, что вы упускаете суть. Все может случиться.

Кроме того, есть много процессоров, и вы не указываете один, поэтому ответить «как процессор обрабатывает деление на 0», конечно, тоже невозможно.

Вы можете перехватывать исключения и обрабатывать их в коде.

person unwind    schedule 04.07.2018
comment
Этот ответ на самом деле больше похож на комментарий, и к тому же довольно язвительный. Можешь перефразировать? - person theMayer; 24.08.2018

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

Есть ряд вещей, которые могут «убить» вашу программу, и все они могут быть классифицированы как исключения в этом отношении:

  • доступ к несуществующей памяти
  • неправильный доступ к памяти (неверное выравнивание, запись только для чтения и т. д.)
  • разделить на 0
  • незаконное обучение
  • превышен лимит ресурсов (например, процессорное время)
  • арифметическое переполнение

В Unix-подобных операционных системах доступ к несуществующей памяти обычно является «нарушением сегментации», а неправильный доступ к памяти обычно является «ошибкой шины». (В Windows они являются/были нарушением общей защиты и/или BSOD.)

И, как вы можете видеть, хотя деление на 0 является исключением, это одно из нарушений сегментации, а не подмножество.

(Я указал арифметическое переполнение как исключение, потому что оно может быть, а не потому, что оно обычно бывает. Большинство современных систем, конечно, не рассматривают переполнение как исключение. Но по правилам C они может, за исключением переполнений целых чисел без знака, которые должны быть определены в C и корректно работать.)

В Unix-подобных операционных системах большинство/все эти исключения, как правило, сопоставляются с сигналами, которые ваша программа может перехватить, чтобы она могла (попытаться) продолжить работу, а не умереть.

(По иронии судьбы, в системе, где я только что попробовал, целочисленное деление на 0 дает мне «исключение с плавающей запятой», а деление с плавающей запятой на 0 дает мне IEEE-754 inf, что вовсе не является исключением. Но это другой вопрос.)

person Steve Summit    schedule 04.07.2018
comment
Это UB: Результатом оператора / является частное от деления первого операнда на второй; результатом оператора % является остаток. В обеих операциях если значение второго операнда равно нулю, поведение не определено. - person user694733; 04.07.2018
comment
@ user694733 Спасибо. (Вы избавили меня от необходимости спускаться вниз за экземпляром Стандарта.) Предложение удалено. - person Steve Summit; 04.07.2018