c++ 在sqrt()中输入负值后,errno不会改变

gpnt7bae  于 2022-12-15  发布在  其他
关注(0)|答案(2)|浏览(220)

使用errno,我试图检查cmath函数是否产生有效的结果,但即使在sqrt()或log()中输入负值,errno仍保持值0,有人知道为什么吗?
环境是macOS Monterey版本12.6.1,编译器是gcc版本11.3.0(Homebrew GCC 11.3.0_1)或苹果clang版本14.0.0(clang-1400.0.29.202)(我试了两个编译器),编译命令是g++ test_errno.cpp -o test_errno -std=c++14
我试过的那段代码是直接从this page复制过来的,下面是代码。

#include <iostream>
#include <cmath>
#include <cerrno>
#include <cstring>
#include <clocale>
 
int main()
{
    double not_a_number = std::log(-1.0);
    std::cout << not_a_number << '\n';
    if (errno == EDOM) {
        std::cout << "log(-1) failed: " << std::strerror(errno) << '\n';
        std::setlocale(LC_MESSAGES, "de_DE.utf8");
        std::cout << "Or, in German, " << std::strerror(errno) << '\n';
    }
}

其结果没有打印错误消息,如果errno设置正确,则应该打印错误消息。

xiozqbni

xiozqbni1#

似乎在macOS上,errno没有被使用,从this bug report到@GAVD的注解。我可以通过math_errhandling的值从@Pete Becker的注解中检查。似乎在C/C++中有两种数学错误处理方式,要么使用errno,要么使用浮点异常,如上面的第二个链接所示。我们可以检查哪种方式系统的数学库通过检查宏常量math_errhandling是否等于MATH_ERREXCEPTMATH_ERRNO来使用(或两者),如下所示(从第二个链接复制):

std::cout << "MATH_ERRNO is "
              << (math_errhandling & MATH_ERRNO ? "set" : "not set") << '\n'
              << "MATH_ERREXCEPT is "
              << (math_errhandling & MATH_ERREXCEPT ? "set" : "not set") << '\n';

在我的系统上,输出是

MATH_ERRNO is not set
MATH_ERREXCEPT is set

,这意味着系统不使用errno来报告数学错误,而是使用浮点异常。这就是为什么errno无论如何都保持值0的原因,我应该使用std::fetestexcept()来检查错误条件。例如,对于浮点异常,std::feclearexcept(FE_ALL_EXCEPT);对应errno = 0;std::fetestexcept(FE_DIVBYZERO)对应errno == ERANGE

yjghlzjz

yjghlzjz2#

我将在黑暗中尝试一下,猜你在你的构建中启用了快速数学?
没有快速数学:
https://godbolt.org/z/vMo1P7Mn1
快速数学:
https://godbolt.org/z/jEsGz7n38
cmath中的错误处理往往会破坏向量化和constexpr (设置外部全局变量,是破坏这两种情况的副作用)。因此,您通常最好自己检查域错误...

相关问题