在编译代码时,使用此选项可大大提高速度。从手册页上可以看到该选项:
在调用执行的数学函数后不要设置“ errno” 一条指令,例如“ sqrt”
我不清楚“ errno”是什么,以及在其他地方如何使用(这与程序的退出代码相同吗?)此外,手册页还说:
依赖IEEE例外进行数学错误处理的程序可能 想要在维护IEEE算术的同时使用此标志来提高速度 兼容性。
我不清楚这是什么意思,是c ++的IEEE例外标准或c ++的通用库(例如Eigen,Boost等)
本质上,我试图确定这是否是在我的代码中使用的“安全”选项,或者我应该从使用它的过程中了解哪些副作用。 previous answer说这可能会影响“线程局部变量”,但我不知道这意味着什么。
编辑:我的代码是一个简单的一次性过程代码,用于处理科学问题。它不会成为需要复杂错误处理的深度嵌入系统的一部分。但是,代码一定不能以微妙的,无声的方式失败。
答案 0 :(得分:3)
C引入了单个errno
或“错误号”的概念,该概念可用于确定某些标准函数(包括数学函数)无法执行其职责的确切原因。 POSIX扩展了errno
,C ++ 11也选择了其中一些扩展。
这些功能之一失败时,the global integer errno
is set to a value that tells you why。显然,这会导致性能下降。
GCC表示,此标志禁用某些数学函数的此行为,从而以节省诊断实用程序和标准合规性的代价来加快程序运行速度。
如果在任何受影响的功能失败时您尚未观察errno
,并且可能不是因为您从未听说过它,那么您将不会失去任何功能。如果您正在编写一个确实受时间限制的程序,或者失败的特定原因并不决定下一步该做什么,则可能是这种情况。 (不过,我建议更广泛地研究错误检查,以确保您的代码具有应有的健壮性。)
但是,如果您有错误,可能会意外地观察到副作用。想象一下,如果您正在执行以下操作:
std::some_maths_function(42);
if (errno == ERANGE)
exit(-1);
糟糕!即使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);
}
当然,您遇到的bug几乎不是GCC的错,但这确实显示了启用此“优化”标志后程序的行为会有所不同。实际上,the documentation说:
任何-O选项都不会打开此选项,因为它可能导致依赖于数学函数的IEEE或ISO规则/规范的确切实现的程序输出不正确。但是,对于不需要这些规范保证的程序,它可能会产生更快的代码。
换句话说,此标志将您发送到书外。但这可能是值得的。
变量errno
必须是线程局部的(也就是说,程序中的每个线程实际上都有一个变量),否则在多线程程序中就没有用了。您可以研究“本地线程”一词,以获取有关此主题的更多信息。