Re: Обработка исключений FPU на C++
От: cserg  
Дата: 17.11.24 20:27
Оценка: 4 (2)
Здравствуйте, Vaynamond, Вы писали:

V>Гуру, подскажите пожалуйста, как правильно под Windows отлавливать исключения FPU на C/C++ ?

V>Пытаюсь с помощью SEH — целочисленное деление на 0 отлавливает, а double не хочет. Т.е. EXCEPTION_FLT_DIVIDE_BY_ZERO вообще мимо кассы.
По умолчанию прерывания от плавающей точки замаскированы. Размаскировать можно используя _control87, _controlfp, __control87_2.

V>Можно, конечно, проверять _statusfp(), и это срабатывает, но зачем тогда EXCEPTION_FLT_* ?

В статье есть пример, когда деление на ноль, не выбрасывающее исключения, может быть полезным. Там же есть пример, как сделать чтобы выбрасывалось исключение. Код из статьи я не проверял.
Обработка исключений FPU на C++
От: Vaynamond Россия  
Дата: 17.11.24 16:32
Оценка:
Гуру, подскажите пожалуйста, как правильно под Windows отлавливать исключения FPU на C/C++ ?
Пытаюсь с помощью SEH — целочисленное деление на 0 отлавливает, а double не хочет. Т.е. EXCEPTION_FLT_DIVIDE_BY_ZERO вообще мимо кассы.
Можно, конечно, проверять _statusfp(), и это срабатывает, но зачем тогда EXCEPTION_FLT_* ?
Re: Обработка исключений FPU на C++
От: kov_serg Россия  
Дата: 17.11.24 16:58
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>Гуру, подскажите пожалуйста, как правильно под Windows отлавливать исключения FPU на C/C++ ?

V>Пытаюсь с помощью SEH — целочисленное деление на 0 отлавливает, а double не хочет. Т.е. EXCEPTION_FLT_DIVIDE_BY_ZERO вообще мимо кассы.
V>Можно, конечно, проверять _statusfp(), и это срабатывает, но зачем тогда EXCEPTION_FLT_* ?

https://en.cppreference.com/w/cpp/numeric/math/isfinite
https://en.cppreference.com/w/cpp/numeric/math/isinf
https://en.cppreference.com/w/cpp/numeric/math/isnan

#include <cmath>
#include <iostream>

double divide(double a,double b) {
    double r=a/b;
    if (!std::isfinite(r)) throw std::overflow_error("Divide by zero exception");
    return r;
}

int main(int argc, char const *argv[]) {
    try {
        double z=divide(1,0);
    } catch(std::overflow_error e) {
        std::cerr<<"ERROR: "<<e.what()<<std::endl;
    }
    return 0;
}


ps: А вы попробуйте целочисленное деление в linux отловить с помощью исключений
Отредактировано 17.11.2024 17:09 kov_serg . Предыдущая версия . Еще …
Отредактировано 17.11.2024 17:07 kov_serg . Предыдущая версия .
Отредактировано 17.11.2024 17:00 kov_serg . Предыдущая версия .
Re: Обработка исключений FPU на C++
От: Zhendos  
Дата: 17.11.24 17:31
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>Гуру, подскажите пожалуйста, как правильно под Windows отлавливать исключения FPU на C/C++ ?


По идее с помощью

#pragma float_control (except, on)


https://learn.microsoft.com/ru-ru/cpp/preprocessor/float-control?view=msvc-170#example
Re[2]: Обработка исключений FPU на C++
От: Vaynamond Россия  
Дата: 17.11.24 18:08
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Здравствуйте, Vaynamond, Вы писали:


V>>Гуру, подскажите пожалуйста, как правильно под Windows отлавливать исключения FPU на C/C++ ?


Z>По идее с помощью


Z>
Z>#pragma float_control (except, on)
Z>


Z>https://learn.microsoft.com/ru-ru/cpp/preprocessor/float-control?view=msvc-170#example


Не помогло
По крайней мере, на MS VS 2005 и 2010.
Re[2]: Обработка исключений FPU на C++
От: Vaynamond Россия  
Дата: 17.11.24 18:21
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Vaynamond, Вы писали:


V>>Гуру, подскажите пожалуйста, как правильно под Windows отлавливать исключения FPU на C/C++ ?

V>>Пытаюсь с помощью SEH — целочисленное деление на 0 отлавливает, а double не хочет. Т.е. EXCEPTION_FLT_DIVIDE_BY_ZERO вообще мимо кассы.
V>>Можно, конечно, проверять _statusfp(), и это срабатывает, но зачем тогда EXCEPTION_FLT_* ?

_>https://en.cppreference.com/w/cpp/numeric/math/isfinite

_>https://en.cppreference.com/w/cpp/numeric/math/isinf
_>https://en.cppreference.com/w/cpp/numeric/math/isnan

_>
_>#include <cmath>
_>#include <iostream>

_>double divide(double a,double b) {
_>    double r=a/b;
_>    if (!std::isfinite(r)) throw std::overflow_error("Divide by zero exception");
_>    return r;
_>}

_>int main(int argc, char const *argv[]) {
_>    try {
_>        double z=divide(1,0);
_>    } catch(std::overflow_error e) {
_>        std::cerr<<"ERROR: "<<e.what()<<std::endl;
_>    }
_>    return 0;
_>}
_>

На MS VS 2010 такое не прокатывает, ругается на std::isfinite
Но это, по сути, аналог _statusfp() с последующим выбросом исключения С++. Такой вариант у меня есть, но ИМХО похоже на костыль.
Вопрос, почему EXCEPTION_FLT_* не срабатывают...

_>ps: А вы попробуйте целочисленное деление в linux отловить с помощью исключений

Про Linux не скажу, а на Windows EXCEPTION_INT_DIVIDE_BY_ZERO спокойно приходит.
Re[3]: Обработка исключений FPU на C++
От: kov_serg Россия  
Дата: 17.11.24 18:40
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>На MS VS 2010 такое не прокатывает, ругается на std::isfinite

https://learn.microsoft.com/ru-ru/cpp/c-runtime-library/reference/finite-finitef?view=msvc-140

template<typename T> bool isfinite(T t) {
    return t == t && 
           t != std::numeric_limits<T>::infinity() &&
           t != -std::numeric_limits<T>::infinity();
}
Отредактировано 17.11.2024 19:27 kov_serg . Предыдущая версия .
Re[2]: Обработка исключений FPU на C++
От: Vaynamond Россия  
Дата: 18.11.24 12:18
Оценка:
Здравствуйте, cserg, Вы писали:

C>Здравствуйте, Vaynamond, Вы писали:


V>>Гуру, подскажите пожалуйста, как правильно под Windows отлавливать исключения FPU на C/C++ ?

V>>Пытаюсь с помощью SEH — целочисленное деление на 0 отлавливает, а double не хочет. Т.е. EXCEPTION_FLT_DIVIDE_BY_ZERO вообще мимо кассы.
C>По умолчанию прерывания от плавающей точки замаскированы. Размаскировать можно используя _control87, _controlfp, __control87_2.
Огромное спасибо!
Я неправильно задал параметры для _controlfp.

V>>Можно, конечно, проверять _statusfp(), и это срабатывает, но зачем тогда EXCEPTION_FLT_* ?

C>В статье есть пример, когда деление на ноль, не выбрасывающее исключения, может быть полезным. Там же есть пример, как сделать чтобы выбрасывалось исключение. Код из статьи я не проверял.
Пример проверил на MSVS 2010, работает корректно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.