Я использую Microsoft Visual C ++ 2010
и у меня есть следующий код, в котором я делю 1 на ноль, как вы видите
#include <cstdio>
int main()
{
int x;
x = 0;
1/x;
while (1) {
std::printf("RUNNING!!\n");
}
}
и удивительно, я не нахожу никаких ошибок во время выполнения, и программа продолжала выполняться и отображает RUNNING !!
Поэтому мой вопрос, почему «1 / x» не считается ошибкой времени выполнения и почему программа не останавливается?
В дополнение ко всем остальным, я замечаю некоторые комментарии о «получении или отсутствии ошибки во время выполнения», которая заставляет меня думать о недопонимании неоднозначной терминологии.
В общепринятой информатике «ошибка времени выполнения» — это не более, чем означает, что компьютерный язык человеческого мозга (простой английский) означает: ошибка, которая замечается во время «выполнения программы».
Так что да, получение дампа из ОС после сигнала является «ошибкой во время выполнения». По крайней мере, для английского языка.
Но это не имеет ничего общего с std::runtime_error
это std::exception
это выбрасывается стандартной библиотекой (или любым другим кодом, основанным на стандартной библиотеке), когда ошибка является фондом в своем собственном коде.
Также термин «исключение» является неоднозначным: в терминологии ОС это «код восстановления», соответствующий драйвер ОС, помещенный в ответ на аппаратную ловушку ЦП. В C ++ это либо базовый класс, представляющий все стандартные ошибки библиотеки, либо независимо от значения субъекта оператора throw.
Дело в том, что целочисленное деление на ноль не стандартная библиотека обнаружила ошибку: базовая целочисленная арифметика рассматривается языком C ++ как примитив среды хостинга. На большинстве платформ operator/(int,int)
реализуется с помощью инструкции ассемблера DIV (по крайней мере, на большей части ЦП), а DIV с операндом 0 обрабатывается микрокодом ЦП как исключение ЦП, которое создает «ловушку» (или прерывание, или как там его называет терминология платформы) ) обрабатывается ОС (или конкретным драйвером ОС). В компиляторе C ++ (и производимом исполняемом файле) нет ничего, что могло бы знать, что происходит во время оценки DIV (поскольку оно является внутренним по отношению к ЦП), поэтому нет бросать оператор, который может быть написан, и, следовательно, нет std :: исключение (или любой другой тип C ++), чтобы поймать. Просто драйвер операционной системы, который можно заменить, и который — по умолчанию — завершает работу приложения.
Это очень похожее поведение эквивалентного по умолчанию catch(...)
в коде запуска C ++, который вызывает main (который вызывает exit), следовательно, еще один источник путаницы.
Чтобы усложнить гораздо больше вещей, оптимизация компилятора может отбросить любую операцию, которая не приводит к используемому результату, и все становится даже невидимым.
Таким образом, вывод результата деления является обязательным, чтобы компилятор не отбрасывал операции. И когда это сделано, наблюдается ловушка ЦП, выдающая сигнал ОС. Это — на простом английском языке «ошибка во время выполнения», но это не C ++ std::runtime_error
поскольку в реализации оператора деления такого оператора выброса не существует.
И наоборот, почему вы думаете, там должен быть ошибкой во время выполнения? Там нет правила, чтобы поручить это.
Это не определено делить на ноль. В этом случае кажется, что, поскольку он может быть перехвачен во время компиляции, ваш компилятор просто проигнорировал операцию… скорее всего потому, что вы никогда не использовали ее «результат».
Итак, эта программа работает и, возможно, ничего не выводит:
int main()
{
int x = 0;
1/x;
}
Тогда как я мог ожидать этот Программа для получения арифметического исключения системного уровня:
#include <iostream>
int main()
{
int x = 0;
int y = 1/x;
std::cout << y << '\n';
}
В общем, когда у вас неопределенное поведение, ничего не ожидайте. Не ожидайте, что ваша программа будет «работать», не ожидайте, что она даст значимый результат, не ожидайте, что она не позвонит вашей бывшей жене и не откажется от законного опекунства ваших домашних цыплят, и не ожидайте, что это вызовет ошибка, которую вы хотели.
Вы не назначали оценку 1/x
в другую переменную. Вот почему вы не получили ошибку времени выполнения.
Если вы измените свой код, как это —
int r;
r = 1/x;
Затем программа остановилась с ошибкой.
Из заметок
Страуструп говорит, в «Дизайн и эволюция C ++» (Аддисон Уэсли,
1994), «события низкого уровня, такие как арифметические переполнения и деление на
ноль, предполагается, что обрабатываются специальным механизмом нижнего уровня
а не по исключениям. Это позволяет C ++ соответствовать поведению
другие языки, когда дело доходит до арифметики. Это также избегает
проблемы, возникающие на сильно конвейерных архитектурах, где происходят события
такие как деление на ноль, являются асинхронными.
Поэтому мой вопрос, почему «1 / х» не считается ошибкой во время выполнения
Вы не присваиваете значение 1 / x какой-либо переменной и, следовательно, получаете любую ошибку во время выполнения. Присвойте его переменной, и вы получите ошибку во время выполнения.