我得到:
warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Wstrict-overflow]
在这一行:
if ( this->m_PositionIndex[in] < this->m_EndIndex[in] )
m_PositionIndex
和 m_EndIndex
类型 itk::Index
( http://www.itk.org/Doxygen/html/classitk_1_1Index.html ),以及他们的 operator[]
返回 signed long
.
(这里是第 37 行:https://github.com/Kitware/ITK/blob/master/Modules/Core/Common/include/itkImageRegionConstIteratorWithIndex.hxx 用于上下文)
任何人都可以在这里解释导致该警告的原因吗?我没有看到模式 (x+c) < x
任何地方 - 因为这只是一个 signed long
比较。
我试图在一个独立的例子中重现它:
#include <iostream>
namespace itk
{
struct Index
{
signed long data[2];
Index()
{
data[0] = 0;
data[1] = 0;
}
signed long& operator[](unsigned int i)
{
return data[i];
}
};
}
int main (int argc, char *argv[])
{
itk::Index positionIndex;
itk::Index endIndex;
for(unsigned int i = 0; i < 2; i++)
{
positionIndex[i]++;
if ( positionIndex[i] < endIndex[i] )
{
std::cout << "something" << std::endl;
}
}
return 0;
}
但我没有收到警告。关于我的演示和真实代码之间有什么不同的想法,或者是什么可能导致真实代码中的警告?我收到带有 -Wall 标志的 gcc 4.7.0 和 4.7.2 的警告。
最佳答案
要简单地禁用此警告,请使用 -Wno-strict-overflow
。 要禁用触发此警告的特定优化,请使用 -fno-strict -overflow
或 -fwrapv
.
gcc manpage描述了这个警告可以用级别来控制:-Wstrict-overflow=n
.
如果由于 -Werror
导致您的构建停止,您可以使用 -Wno-error=strict-overflow
(或者只是-Wno-error
覆盖 -Werror
)。
分析和评论...
我收到了同样的警告,并花了几个小时试图在一个较小的示例中重现它,但从未成功。我的真实代码涉及在模板类中调用内联函数,但算法简化为以下...
int X = some_unpredictable_value_well_within_the_range_of_int();
for ( int c=0; c<4; c++ ) assert( X+c >= X ); ## true unless (X+c) overflows
在我的例子中,警告与展开 for
循环的优化器有某种关联,因此我能够通过声明 volatile int c=0
来解决问题。修复它的另一件事是声明 unsigned int c=0
,但我不确定为什么会有所作为。修复它的另一件事是使循环计数足够大以至于循环不会被展开,但这不是一个有用的解决方案。
那么这个警告的真正含义是什么?要么是说优化器修改了你的算法的语义(假设没有溢出),要么只是告诉你优化器假设你的代码没有未定义的行为 溢出有符号整数。除非溢出有符号整数是您的程序预期行为的一部分,否则此消息可能并不表示您的代码存在问题——因此您可能希望在正常构建时禁用它。如果您收到此警告但不确定有问题的代码,使用 -fwrapv
禁用优化可能是最安全的。
顺便说一句,我在 GCC 4.7 上遇到了这个问题,但是使用 4.8 编译的相同代码没有警告——这可能表明 GCC 开发人员认识到在正常情况下需要不那么“严格”(或也许这只是由于优化器的差异)。
哲学...
在 [C++11: N3242 $5.0.4],它说...
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.
这意味着符合标准的编译器可以简单地假设不会发生溢出(即使对于无符号类型)。
在 C++ 中,由于模板和复制构造函数等特性,elision无意义的操作是重要的优化器能力。但是,有时,如果您将 C++ 用作低级“系统语言”,您可能只是希望编译器按照您的要求执行操作——并依赖于底层硬件的行为。鉴于标准的语言,我不确定如何以独立于编译器的方式实现这一点。
关于c++ - 不明白 "assuming signed overflow"警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12984861/