Предупреждение об оптимизации C ++ STL: проблема с кодом или что-то более зловещее? - PullRequest
9 голосов
/ 29 января 2011

У меня есть программа, над которой я работаю, где я переключаюсь с использования массивов на векторы, но у меня возникает проблема.Я сократил его до этого:

#include <vector>

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

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

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

A::~A(void) {}

Это дает следующее предупреждение от g ++ (флаги: -O2 -Wunsafe-loop-optimizations, версия 4.4.3 (Ubuntu 4.4.3-4ubuntu5) наUbuntu 10.04 x86_64):

/usr/include/c++/4.4/bits/stl_construct.h: в деструкторе 'A :: ~ A ()': /usr/include/c++/4.4/bits / stl_construct.h: 92: предупреждение: невозможно оптимизировать цикл, счетчик цикла может переполниться

Итак, что дает Лео?Разве векторный класс не должен отслеживать, сколько у него элементов?Итак, если это «счетчик», на который ссылаются, как он может переполниться?( Редактировать : на этот вопрос более или менее дан ответ ниже, но, на мой взгляд, остается только следствие: зачем беспокоиться о том, что цикл в библиотеке не может быть оптимизирован?пользователь, беспокоиться об этом?)

Редактировать :

Вот соответствующий код жалобы (но, как я уже сказал в комментариях, я непонимаю, почему это должно быть моим соображением, поскольку мне не нужно беспокоиться о реализации библиотеки):

/**
 * 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 :

ОК, спасибо за информацию, ребята:это ошибка в компиляторе.Просто для справки, я скомпилировал unmoled компилятор и библиотеку c ++ из GNU (версия 4.5.2), которая не отображает это поведение (код библиотеки идентичен), поэтому я предполагаю, что подобные предупреждения не должны появляться.Еще раз спасибо всем.

Ответы [ 3 ]

6 голосов
/ 29 января 2011

Это просто означает, что компилятор не может доказать , что он не будет переполнен.Поскольку у вас включен -O2, вы запрашиваете определенную оптимизацию для циклов.Некоторые из этих оптимизаций могут быть выполнены, только если эти условия могут быть доказаны.Запрошенное вами предупреждение компилятора говорит о том, что некоторые циклы не могут быть оптимизированы (я предполагаю, что это встроенный цикл уничтожения для базового массива вектора, вероятно.

Вы можете игнорировать это предупреждение, я думаю.нужно ли удивляться, почему вы спросили об этом предупреждении в параметрах компиляции?

2 голосов
/ 29 января 2011

Кажется, я наконец понял, на что намекал компилятор.

Цикл не выполняется для целого числа, поэтому я думаю, что компилятор пытается сказать, что он на самом деле не может вычислить, сколько циклов выполнит цикл.

Предупреждение, которое вы использовали, на самом деле обычно связано с -funsafe-loop-optimizations, со страницы параметров оптимизации gcc :

-funsafe-loop-optimizations Если задано, оптимизатор цикла предположит, что индексы цикла не переполняются, и что циклы с нетривиальным условием выхода не бесконечны. Это обеспечивает более широкий диапазон оптимизации цикла, даже если сам оптимизатор цикла не может доказать, что эти предположения верны. Используя -Wunsafe-loop-optimizations`, компилятор предупредит вас, если найдет цикл такого типа.

Должен признать, я думал, что компилятору всегда разрешалось предполагать, что цикл в конце концов прекратится, потому что для его определения потребуется решение проблемы остановки, которая не может быть решена в общем случае.

Но здесь, если вы посмотрите на функцию, невозможно доказать, что цикл не переполнится по простой причине: диапазон от first до last может быть неправильным.

  • это может быть first > last (примечание: нельзя сравнивать прямые итераторы)
  • Возможно, что выравнивания * отключены, по указателям (T*) ++ эквивалентно += sizeof(T), а поскольку вместо < используется !=, first может перепрыгнуть last если это так

Конечно, на практике этого никогда не произойдет, потому что разработчики библиотек позаботились о том, чтобы они передали правильные аргументы методу, но компилятор не может вывести его, таким образом предупреждение.

Тем не менее, я удивлен, я бы подумал, что авторы компиляторов намеренно игнорируют предупреждения, выдвинутые их собственными библиотеками, потому что им приходилось использовать эти слабые руки просто так, чтобы мы этого не делали.

(*) Здесь не выравнивание памяти, я просто намекаю на тот факт, что неправильно откалиброванный T* может фактически указывать в пределах T и что продвижение sizeof(T) за один раз фактически никогда не позволит ему когда-либо успокоиться обратно на T границу ...

1 голос
/ 30 января 2011

Ваш код невиновен.

Предупреждение должно быть ошибкой компилятора gcc (по крайней мере, имеющейся у вас версии) или используемой ими реализации stl. Вы должны ожидать, что не получите строго никаких предупреждений о правильном коде.

...