不了解“假设签名溢出”警告 [英] Don't understand "assuming signed overflow" warning

查看:153
本文介绍了不了解“假设签名溢出”警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到:


警告:假设(X + c)< X始终为假[-Wstrict-overflow]


在此行:

  if(this-> m_PositionIndex [in]< this-> m_EndIndex [in])

m_PositionIndex m_EndIndex 类型为 itk的$ p $: :索引 http://www.itk.org/Doxygen/html/classitk_1_1索引。 html ),然后其 operator [] 返回一个签名长的 c。



(此处是第37行: https ://github.com/Kitware/ITK/blob/master/Modules/Core/Common/include/itkImageRegionConstIteratorWithIndex.hxx 作为上下文)



任何人都可以在这里解释什么会导致该警告?我没有看到(x + c)< x 随处可见-因为这只是一个签名的长比较。



我试图

  #include< iostream> 

命名空间itk
{
结构索引
{
签名长数据[2];

Index()
{
data [0] = 0;
data [1] = 0;
}

签署长期& operator [](unsigned int i)
{
返回数据[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<< 某物<< std :: endl;
}
}

返回0;
}

但我没有收到警告。关于我的演示和实际代码之间有什么不同的任何想法,或者在实际代码中可能引起警告的原因是什么?我同时收到带有-Wall标志的gcc 4.7.0和4.7.2的警告。

解决方案

要禁用此警告,请使用 -Wno-strict-overflow 要禁用触发该警告的特定优化,请使用 -fno-严格溢出 -fwrapv



gcc手册页描述了可以通过以下级别控制此警告: -Wstrict-overflow = n



如果由于 -Werror 而导致构建停止,则可以解决而不使用 -Wno-error = strict-overflow 隐藏警告(或仅使用 -Wno-error 覆盖-恐怖)。






分析和评论... p>

我得到了同样的警告,并花了几个小时试图在一个较小的示例中重现它,但从未成功。我的实际代码涉及在模板化类中调用内联函数,但是该算法简化为以下内容……

  int X = some_unpredictable_value_well_within_the_range_of_int(); (int c = 0; c< 4; c ++)的
assert(X + c> = X); ##除非(X + c)溢出

是真,否则我的警告与优化器相关展开 for 循环,因此我能够通过声明 volatile int c = 0 来解决。解决该问题的另一件事是声明了 unsigned int c = 0 ,但是我不确定为什么会有所不同。解决该问题的另一件事是使循环计数足够大,以至于不会展开该循环,但这不是一个有用的解决方案。



那么,此警告的真正含义是什么? ?要么说优化器已经修改了算法的语义(假设没有溢出),要么只是通知您优化器假设您的代码没有未定义的行为溢出有符号整数。除非溢出带符号的整数是程序预期行为的一部分,否则此消息可能并不表示代码中有问题-因此,您可能希望针对常规构建禁用它。如果收到此警告,但不确定所涉及的代码,最安全的方法是使用 -fwrapv 禁用优化。



顺便说一句,我在GCC 4.7上遇到了这个问题,但是使用4.8编译时未经过警告的相同代码-可能表明GCC开发人员认识到,在






哲学...



在[C ++ 11: N3242 $ 5.0.4],它指出...


如果在评估表达式,其结果不是
的数学定义值,或者不在其类型的
的可表示值范围内,行为未定义。


这意味着符合条件的编译器可以简单地假设永不发生溢出(即使对于无符号类型)。



在C ++中,由于模板和副本构造函数之类的功能,省略是重要的优化程序功能。但是有时候,如果您使用C ++作为低级系统语言,则可能只希望编译器按照您的要求执行操作-并依赖底层硬件的行为。考虑到标准的语言,我不确定如何以与编译器无关的方式实现这一目标。


I am getting:

warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Wstrict-overflow]

on this line:

if ( this->m_PositionIndex[in] < this->m_EndIndex[in] ) 

m_PositionIndex and m_EndIndex of type itk::Index (http://www.itk.org/Doxygen/html/classitk_1_1Index.html), and their operator[] returns a signed long.

(it is line 37 here: https://github.com/Kitware/ITK/blob/master/Modules/Core/Common/include/itkImageRegionConstIteratorWithIndex.hxx for context)

Can anyone explain what would cause that warning here? I don't see the pattern (x+c) < x anywhere - as this is simply a signed long comparison.

I tried to reproduce it in a self-contained example:

#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;
}

but I do not get the warning there. Any thoughts as to what is different between my demo and the real code, or what could be causing the warning in the real code? I get the warning with both gcc 4.7.0 and 4.7.2 with the -Wall flag.

解决方案

To simply disable this warning, use -Wno-strict-overflow. To instead disable the specific optimization that triggers this warning, use -fno-strict-overflow or -fwrapv.

The gcc manpage describes that this warning can be controlled with levels: -Wstrict-overflow=n.

If this is stopping your build due to -Werror, you can work-around without hiding the warnings by using -Wno-error=strict-overflow (or just -Wno-error to override -Werror).


Analysis and commentary...

I got the same warning and spent a couple of hours trying to reproduce it in a smaller example, but never succeeded. My real code involved calling an inline function in a templated class, but the algorithm simplifies to the following...

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

In my case the warning was somehow correlated with the optimizer unrolling the for loop, so I was able to work-around by declaring volatile int c=0. Another thing that fixed it was to declare unsigned int c=0, but I'm not exactly sure why that makes a difference. Another thing that fixed it was making the loop count large enough that the loop wouldn't be unrolled, but that's not a useful solution.

So what is this warning really saying? Either it is saying that the optimizer has modified the semantics of your algorithm (by assuming no overflow), or it is simply informing you that the optimizer is assuming that your code doesn't have the undefined behavior of overflowing a signed integer. Unless overflowing signed integers is part of the intended behavior of your program, this message probably does not indicate a problem in your code -- so you will likely want to disable it for normal builds. If you get this warning but aren't sure about the code in question, it may be safest to just disable the optimization with -fwrapv.

By the way, I ran into this issue on GCC 4.7, but the same code compiled without warning using 4.8 -- perhaps indicating that the GCC developers recognized the need to be a bit less "strict" in the normal case (or maybe it was just due to differences in the optimizer).


Philosophy...

In [C++11:N3242$5.0.4], it states...

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.

This means that a conforming compiler can simply assume that overflow never occurs (even for unsigned types).

In C++, due to features such as templates and copy constructors, elision of pointless operations is an important optimizer capability. Sometimes though, if you are using C++ as a low-level "system language", you probably just want the compiler to do what you tell it to do -- and rely on the behavior of the underlying hardware. Given the language of the standard, I'm not sure how to achieve this in a compiler-independent fashion.

这篇关于不了解“假设签名溢出”警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆