c++ - 不明白 "assuming signed overflow"警告

标签 c++ gcc gcc-warning

我得到:

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_PositionIndexm_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/

相关文章:

c++ - 全局变量中的动态内存分配错误

c++ - 通过引用将指针传递给函数时如何使用&号和星号

gcc - OpenMP 是否支持工作窃取机制?

c++ - GCC - 多个预编译头文件和特定路径

c++ - 将 GCC 中的 'delete' 警告变为错误

java - Eclipse for Java - 运行类似 C++ 的代码块 #ifdef DEBUG

c++ - [basic.def.odr]/3 中的短语 `if x is an object` 的用途是什么?

gcc - 链接描述文件中的位置计数器 (.) 更新

c - 隐式声明警告 : What are the built-in functions?

c++ - Eigen 与 -O3 警告 : argument 1 value ‘X’ exceeds maximum object size Y