使用 gcc 的 -fno-math-errno 可能产生哪些副作用?

Dan*_*and 3 c++ gcc g++

在编译我的代码时使用这个选项获得了巨大的加速。从手册页它说这个选项:

在调用使用单条指令执行的数学函数后不要设置“errno”,例如“sqrt”

我不清楚“errno”是什么,以及它是如何在其他地方使用的(这与程序的退出代码相同吗?)此外,手册页说:

依赖 IEEE 异常进行数学错误处理的程序可能希望使用此标志来提高速度,同时保持 IEEE 算术兼容性。

我不清楚这意味着什么,是 c++ 的 IEEE 例外标准或 c++ 的公共库(例如 Eigen、Boost 等)

本质上,我试图确定这是否是在我的代码中使用的“安全”选项,或者我应该从使用中了解哪些副作用。一个以前的回答说,这可能会影响“线程局部变量”,但我不知道这意味着什么。

编辑:我的代码是一个简单的一次性程序代码,用于处理科学问题。它不会成为需要复杂错误处理的深度嵌入系统的一部分。但是,代码不能以微妙、无声的方式失败。

Lig*_*ica 5

C 引入了单个errno或“错误编号”的概念,可用于确定某些标准函数(包括数学函数)无法执行其职责的确切原因。POSIX 扩展errno,C++11 也选择了其中的一些扩展。

当这些函数之一失败时,全局整数errno被设置为一个值,告诉您为什么。显然,这会导致性能损失。

GCC 说这个标志禁用了某些数学函数的这种行为,以诊断实用程序和标准合规性为代价来加速你的程序。

如果您已经没有注意到errno任何受影响的功能何时发生故障,并且您可能没有注意到,因为您从未听说过它,那么您将不会失去任何功能。如果您正在编写一个真正有时间限制的程序,或者当失败的特定原因没有决定您的代码下一步做什么时,情况可能就是这种情况。(不过,我建议更广泛地研究错误检查,以确保您的代码尽可能健壮。)


但是,如果您有错误,您可能会意外地观察到副作用。想象一下,如果您正在执行以下操作:

std::some_maths_function(42);
if (errno == ERANGE)
   exit(-1);
Run Code Online (Sandbox Code Playgroud)

哎呀!errno即使some_maths_function(42)成功,我们也在检查。假设上面这段代码是一个调用std::some_other_maths_function(999),通常会失败并导致errno设置为EDOM。这掩盖了上面代码中的错误。

现在打开编译器标志。如果some_other_maths_function是不再设置的函数之一,则errno您的错误将被揭露,您可能需要一些时间才能意识到您应该编写更像的内容:

if (std::some_maths_function(42) == -1)
{
   if (errno == RANGE)
      exit(-1);
}
Run Code Online (Sandbox Code Playgroud)

当然,您有错误几乎不是 GCC 的错,但这确实显示了启用此“优化”标志后程序的行为会有何不同。确实,文档说:

此选项不会被任何 -O 选项打开,因为它可能导致依赖于数学函数的 IEEE 或 ISO 规则/规范的精确实现的程序的错误输出。然而,对于不需要这些规范保证的程序,它可能会产生更快的代码。

换句话说,此标志会向您发送书外信息。但这可能是值得的。


该变量errno必须是线程局部的(也就是说,程序中的每个线程实际上都有一个),否则它在多线程程序中将毫无用处。您可以研究术语“线程本地”以获取有关此主题的更多信息。