繁体   English   中英

C ++ STL优化警告:代码问题还是更险恶的?

[英]C++ STL optimization warning: problem with the code or something more sinister?

我有一个程序,我正在从使用数组切换到向量,但我遇到了问题。 我把它减少到了这个:

#include <vector>

class A {
public:
A(void);
~A(void);

private:
std::vector< std::vector<int> > a;
};

A::A(void) : a() {}

A::~A(void) {}

这给出了来自g ++(flags:-O2 -Wunsafe-loop-optimizations,版本4.4.3(Ubuntu 4.4.3-4ubuntu5)在Ubuntu 10.04 x86_64上)的以下警告:

那么,Leo给出了什么? 矢量类不应该跟踪它有多少元素? 那么,如果这是被引用的“计数器”,它怎么会溢出? 编辑 :这个问题或多或少已在下面得到解答,但是,对我来说,只留下必然结果:为什么还要警告库中的循环无法优化?为什么我,最终用户,应该关注那个问题? ?)

编辑

这是关于被抱怨的相关代码(但是,正如我在评论中所说,我不明白为什么这应该是我的考虑因为我不应该担心库的实现):

/**
 * Destroy the object pointed to by a pointer type.
 */
template<typename _Tp>
  inline void
  _Destroy(_Tp* __pointer)
  { __pointer->~_Tp(); }

template<bool>
  struct _Destroy_aux
  {
    template<typename _ForwardIterator>
      static void
      __destroy(_ForwardIterator __first, _ForwardIterator __last)
    {
      for (; __first != __last; ++__first) // <-- this is line 92
        std::_Destroy(&*__first);
    }
  };

更新

好吧,我期待两个答案中的一个:我在我的代码中做了一些巧妙的异常(但不一定错误),或者消息非常字面地告诉我,库中指向的循环无法优化。 感激地保证它不是前者,是否会报告来自gcc的自己的库预期行为的警告,还是应该报告? (似乎不值得提出另一个问题来问这个新问题的借口。)

更新2

好的,感谢所有信息人员:这是编译器中的一个错误。 仅供参考,我从GNU(版本4.5.2)编译了一个不受干扰的编译器和c ++库,它没有显示这种行为(库代码是相同的),所以我想这样的警告不应该出现。 再次感谢大家。

它只是意味着编译器无法证明它不会溢出。 由于你有-O2,你要求对循环进行某些优化。 只有在可以证明这些条件的情况下,才能完成其中一些优化。 您要求的编译器警告告诉您某些循环无法优化(我猜它可能是矢量底层数组的内联破坏循环。

我想你可以忽略这个警告。 但是我不得不想知道为什么你首先在编译选项中要求这个警告?

我想我终于得到了编译器所暗示的内容。

循环不是在整数上执行的,所以我认为编译器试图告诉的是它实际上无法计算循环将执行的运行次数。

您使用的警告实际上通常应该与-funsafe-loop-optimizations结合使用,来自gcc optimize options页面

-funsafe-loop-optimizations如果给定,循环优化器将假定循环索引不会溢出,并且具有非平凡退出条件的循环不是无限的。 即使循环优化器本身无法证明这些假设是有效的,这也可以实现更广泛的循环优化。 使用-Wunsafe-loop-optimizations`,编译器会在发现这种循环时发出警告。

我必须承认,我认为编译器总是被允许假设一个循环最终会终止,因为推导它将需要解决在一般情况下无法解决的暂停问题。

但在这里,如果你看的功能,这是不可能的证明,循环不会溢出的原因很简单:在范围内firstlast可能会形成不良。

  • 它可能是first > last (注意:一个不能比较前向迭代器)
  • 可能是对齐*关闭,指针( T*++相当于+= sizeof(T) ,并且因为使用了!=而不是< ,如果是这样的话, first可以跳过last

当然,它在实践中永远不会发生,因为库编写者已经确保它们向方法传递了正确的参数,但编译器无法推断它,因此警告。

我仍然感到惊讶,我会认为编译器编写者会故意忽略他们自己的库提出的警告,因为他们不得不使用那些轻微的手,以便我们不这样做。

(*)这里没有内存对齐,我只是暗示一个错误校准的T*实际上可能指向T内的事实,并且一次推进sizeof(T)实际上永远不会让它永远地回到T边界...

你的代码是无辜的。

警告必须是gcc编译器(至少是您当前拥有的版本)或它们使用的stl实现的错误。 您应该期望严格没有关于正确代码的警告。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM