Обработка деления на ноль с помощью <csignal>приводит к неожиданному поведению - PullRequest
0 голосов
/ 09 июля 2020

Я пытался обработать целочисленное деление на ноль (пожалуйста, не судите, мне сказали, что я должен использовать <csignal> lib, и я не мог просто использовать оператор if), но мне нужно было убедиться, что программа продолжала бы работать (хотя это очень плохая практика) вместо сбоя или закрытия. Странно то, что программа должна обрабатывать только деление на ноль, но должна выходить для всех других типов SIGFPE.

SideNote : Теперь я не понимаю, почему они используют такие имена, как FPU или FE или FPE при обращении к целым «исключениям» (или, я бы сказал, прерываниям), поскольку в стандарте четко указано, что деление числа с плавающей запятой должно возвращать либо inf, либо nan вместо 0 / 0 (скажите, если я ошибаюсь).

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

#include <iostream>
#include <csignal>

using namespace std;

int x = 0;

void handle(int s);

int main(int argc, char * argv[]) {
    signal(SIGFPE, handle);
    cout << "Insert 0: ";
    cin >> x; // here I would input 0, so the program can compile
    x = 5 / x;
    cout << "X: " << x << endl;
    return 0;
}

void handle(int s) {
    if (s != FPE_INTDIV) exit(1);
    cout << "sig: " << s << endl;
    x = 1;
}

Как вы видите, я использовал FPE_INTDIV, чтобы исключить все остальные типы исключений, но это не работает. В конце концов я обнаружил, что FPE_INTDIV - это константа symboli c для 7 (это то, что мне сообщает intellisense vs-code), и если бы я напечатал значение s, это было бы 8. Я обнаружил, что, как ни странно, 8 - это значение для FPE_INTOVF, для которого в документации указано, что он специально разработан для целочисленных переполнений. целочисленное деление, если есть символ c для целочисленного деления? Что мне не хватает? Кто-то испортил значения в библиотеке? Я использую неправильные макросы?

Я также должен упомянуть, этот код отлично компилируется с clang ++ и g ++ , но при компиляции на компьютере Windows с cl , он сообщает мне, что для FPE_INTDIV нет макроса.

Как я могу быть уверен в том, что я делаю, и написать кроссплатформенное решение, которое работает?

I уже чувствую себя идиотом.

1 Ответ

2 голосов
/ 09 июля 2020

Это определяется как:

Сигнал SIGFPE сообщает о фатальной арифметической ошибке c. Хотя название происходит от «исключения с плавающей запятой», этот сигнал фактически охватывает все арифметические c ошибки, включая деление на ноль и переполнение. Если программа хранит целочисленные данные в месте, которое затем используется в операции с плавающей запятой, это часто вызывает исключение «недопустимая операция», поскольку процессор не может распознать данные как число с плавающей запятой.

Нет причин для его особого обозначения FPE, но такого рода ярлыки могут развиваться непредсказуемым образом. Я бы не стал вдаваться в подробности.

Эти сигналы являются частью стандарта POSIX и могут не полностью поддерживаться или реализовываться в Windows. Реализация этих средств поддержки Windows отсутствует в ряде областей, например, как fork() не поддерживается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...