【问题标题】:errno value is not updated (c++)errno 值未更新 (c++)
【发布时间】:2016-08-07 15:01:16
【问题描述】:

我是编码新手(目前正在学习 c++,我对 C 有点了解)...

正在阅读 math.h 中的函数并阅读 errno...

根据我提到的网站:-

域错误(输入参数超出了数学定义的运算范围,例如 std::sqrt(-1)、std::log(-1) 或 std::acos(2))。如果设置了 MATH_ERRNO 位,则将 EDOM 分配给 errno。如果设置了 MATH_ERREXCEPT 位,则引发 FE_INVALID。

所以我尝试用这些知识编写一个小程序......

#include <iostream>
#include <cerrno>
#include <cmath>
using namespace std;

int main (void)
{
  errno = 0;
  cout<<"\nWhat I get :-\n";
  cout << "log(-3) = " << log(-3) << "\n"; 
  //shouldn't it do (errno = EDOM) in the above step?
  cout << "errno = " << errno << "\n";
  cout << strerror(errno) << "\n";

  errno = EDOM;
  cout<<"\nWhat I want :-\n";
  cout << "log(-3) = " << log(-3) << "\n";
  cout << "errno = " << errno << "\n";
  cout << strerror(errno) << "\n\n";

  return(0);
}

在输出中,我看到 errno 在我的第一个块中没有更新为 EDOM,即使 -3 不在 log() 的域中...

输出:-

What I get :-
log(-3) = nan
errno = 0
Undefined error: 0

What I want :-
log(-3) = nan
errno = 33
Numerical argument out of domain

我不明白我在这里错过了什么...... 请帮忙....

我正在 Mac 中的 Apple LLVM 版本 7.3.0 (clang-703.0.31) 上编译我的代码。

【问题讨论】:

  • std::ends 对普通文本流没有意义。并且不要使用std::endl,除非你需要它做的额外的东西。 '\n' 结束一行。

标签: c++


【解决方案1】:

#define MATH_ERRNO 1 是非法的。您不应该重新定义标准库符号。 MATH_ERRNO 已按标准定义为 1。

您无法设置实现如何处理错误(除了编译器特定的开关。请阅读编译器的文档)。你只能检查它:

if (math_errhandling & MATH_ERRNO)
    std::cout << "Error reporting uses errno\n";
else 
    std::cout << "Error reporting does not use errno\n";

if (math_errhandling & MATH_ERREXCEPT)
    std::cout << "Error reporting uses floating-point exceptions\n";
else 
    std::cout << "Error reporting does not use floating-point exceptions\n";

对于 clang,相关标志是 -fmath-errno/-fmath-no-errno 使用/不使用 errno

discussion on reported bug看来,标准库的Mac实现根本不使用errno。所以如果你想用它来报告错误,你就不走运了。

【讨论】:

  • 好的...我删除了#define语句...我在删除它后运行了代码,我得到了第二个选项“错误报告不使用errno”......跨度>
  • @Abhijith 我已经更新了帖子。似乎这是 Mac 特有的行为。
  • @Abhijith 我可以成功地将 errno 设置为 2。好吧,可以将它设置为任何你喜欢的。它只是一个变量。问题实际上是标准库没有设置它。 这是 Mac 上的基本功能吗 我不是 Mac 专家,但似乎是的,与 Mac 捆绑在一起的标准库不使用 errno。潜在的解决方案是找到使用它的库,编译它并静态链接到你的程序,但现在,对你来说,这将比它的价值更麻烦。
  • 你的答案和时间...... :)
【解决方案2】:

您可以在以下位置找到数学错误处理的完整示例(C 语言):http://www.cplusplus.com/reference/cmath/math_errhandling/ 有关该站点的完整性示例:

#include <stdio.h>      /* printf */
#include <math.h>       /* math_errhandling */
#include <errno.h>      /* errno, EDOM */
#include <fenv.h>       /* feclearexcept, fetestexcept, FE_ALL_EXCEPT, FE_INVALID */
#pragma STDC FENV_ACCESS on

int main () {
  errno = 0;
  if (math_errhandling & MATH_ERREXCEPT) feclearexcept(FE_ALL_EXCEPT);

  printf ("Error handling: %d",math_errhandling);

  sqrt (-1);
  if (math_errhandling & MATH_ERRNO) {
    if (errno==EDOM) printf("errno set to EDOM\n");
  }
  if (math_errhandling  &MATH_ERREXCEPT) {
    if (fetestexcept(FE_INVALID)) printf("FE_INVALID raised\n");
  }

  return 0;
}

【讨论】:

  • 我收到警告说“不支持编译指示 STDC FENV_ACCESS ON,忽略编译指示 [-Wunknown-pragmas]”......所以我不确定输出是否是它应该的是......我得到你发布的代码的输出:“错误处理:2”
  • @Abhijith 错误处理:2 表示设置了 MATH_ERREXCEPT 而未设置 MATH_ERRNO。
  • 这意味着函数使用的错误处理机制是 MATH_ERREXCEPT 是什么意思,请查看提供的链接中的表格。附言我现在没有 clang 编译器,所以我现在无法检查未知的编译指示警告
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
  • 2016-06-12
  • 2013-07-24
  • 2018-06-12
  • 1970-01-01
  • 2019-04-10
  • 2011-07-25
相关资源
最近更新 更多