开发者

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

I have a program that I'm working on where I'm switching from using arrays to vectors, but I get a problem. I've reduced it down to this:

#include <vector>

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

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

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

A::~A(void) {}

This gives the following warning from g++ (flags: -O2 -Wunsafe-loop-optimizations, version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) on Ubuntu 10.04 x86_64):

/usr/include/c++/4.4/bits/stl_construct.h: In destructor ‘A::~A()’: /usr/include/c++/4.4/bits/stl_construct.h:92: warning: cannot optimize loop, the loop counter may overflow

So, what gives, Leo? Shouldn't the vector class keep track of how many elements it has? So, if that is the "counter" being referenced, how can it overflow? (Edit: this question has more or less been answered below, but, to me, only leaves the corollary: why bother warning that a loop in the library can't be optimized? Why should I, the end user, be concerned with that?)

Edit:

Here is the relevent code being complained about (but, as I said in the comments, I don't see why that should be a consideration of mine as I shouldn't need to worry about the implementation of the library):

/**
 * 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);
    }
  };

Update:

OK, I was anticipating one of either two answers: that I was doing something subtly abnormal (but not necessarily wrong) in my code, or that the message was very literally telling me that the loop pointed to in the library could not be optimized. Gratefully reassured that it was not the former, is reporting warnings from its own library expected behaviour from gcc, or should it be reported? (It doesn't seem worth opening another question to ask this so excuse this new questioning.)

Update 2:

OK, thanks for all the info guys: it's a bug in the compiler, then. Just for reference, I compiled an unmolested compiler and c++ library from GNU (version 4.5.2), which does not display this behaviour (the library code is identical), so I guess that warnings like 开发者_StackOverflow中文版this are not supposed to come up. Thanks again, everyone.


It just means the compiler cannot prove that it will not overflow. Since you have -O2 on, you are asking for certain optimizations to be done for loops. Some of these optimizations can only be done if these conditions can be proven. The compiler warning you have asked for is telling you that some loops could not be optimized (I am guessing it is the inline destruction loop for the vector's underlying array probably.

You could disregard this warning I think. However I do have to wonder why you asked for this warning in the compile options in the first place?


I think I finally got what the compiler was hinting at.

The loop is not executed on an integer, so I think what the compiler is trying to tell is that it cannot actually compute how many runs the loop will perform.

The warning you used should actually is usually coupled with -funsafe-loop-optimizations, from gcc optimize options page:

-funsafe-loop-optimizations If given, the loop optimizer will assume that loop indices do not overflow, and that the loops with nontrivial exit condition are not infinite. This enables a wider range of loop optimizations even if the loop optimizer itself cannot prove that these assumptions are valid. Using -Wunsafe-loop-optimizations`, the compiler will warn you if it finds this kind of loop.

I must admit I thought the compiler was always allowed to assume a loop would terminate eventually because deducing it would require solving the halting problem which cannot be solved in the general case.

But here, if you look at the function, it's impossible to prove that the loop will not overflow for a simple reason: the range first to last may be ill-formed.

  • it could be that first > last (note: one cannot compare forward iterators)
  • it could be that the alignments* are off, on pointers (T*) ++ is equivalent to += sizeof(T), and because a != is used instead of <, first could jump over last if that is the case

Of course, it'll never happen in practice, because the library writers have ensured that they passed correct arguments to the method, but the compiler cannot deduce it, thus the warning.

Still I am surprised, I would have thought that compiler writers would purposely ignore the warnings raised by their own libraries because they had to employ those slight of hands just so that we don't.

(*) Not memory alignment here, I am merely hinting at the fact that a wrongly calibered T* could actually point within a T and that advancing sizeof(T) at a time would never actually allow it to ever settle back on a T boundary...


Your code is innocent.

The warning must be a fault of gcc compiler (at least, of the version you currently have) or the stl implementation they use. You should expect to get strictly no warnings about the correct code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜