Мой g++ генерирует странное предупреждение с помощью метода vector<weak_ptr> erase ()
У меня есть следующий код C++:
#include <memory>
#include <vector>
#include <string>
#include <unordered_map>
void erase_from_vector(std::vector<std::weak_ptr<int>> &mvec) {
for (auto mvec_it = mvec.begin(); mvec_it != mvec.end(); )
mvec_it = mvec.erase(mvec_it);
}
int main(void) {
#if 0
std::vector<std::weak_ptr<int>> mvec;
for (auto mvec_it = mvec.begin(); mvec_it != mvec.end(); )
mvec_it = mvec.erase(mvec_it);
#endif
}
GCC выдает предупреждение, когда я компилирую это следующим образом:
ppk@fif-cloud-dev:~$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
ppk@fif-cloud-dev:~$ g++ -fstrict-overflow -Wstrict-overflow=5 -O2 -std=c++14 warn1.cc
warn1.cc: In function ‘void erase_from_vector(std::vector<std::weak_ptr<int> >&)’:
warn1.cc:6:6: warning: assuming signed overflow does not occur when changing X +- C1 cmp C2 to X cmp C2 -+ C1 [-Wstrict-overflow]
void erase_from_vector(std::vector<std::weak_ptr<int>> &mvec) {
^
Но когда я изменяю флаг -O2 на -O1, он компилируется без каких-либо предупреждений. Когда я сохраняю флаг -O2 и код комментария в main(), он также компилируется без каких-либо предупреждений. Компилятор Clang также не выдает никаких предупреждений.
Я полагаю, что это предупреждение исходит от деструктора std::weak_ptr, где счетчик уменьшается, но я не знаю, почему он появляется в моем коде.
Это предупреждение вызвано моей ошибкой или ошибкой в компиляторе?
1 ответ
Скорее всего, причуда gcc 5.4. Он исчезнет, как только вы доберетесь до gcc 6.1, и я не вижу его снова в более поздней версии.
gcc 5.4 (предупреждения)
gcc 6.1 (без предупреждений)
Особенно ужасно, что Кланг не воспроизводит поведение.
Следует отметить, что такое поведение не совсем ошибка, согласно документации (выделено мое)
Оптимизация, которая предполагает, что подписанное переполнение не происходит, совершенно безопасно, если значения задействованных переменных таковы, что переполнение фактически никогда не происходит. Поэтому это предупреждение может легко дать ложное срабатывание: предупреждение о коде, который на самом деле не является проблемой.
Что вы используете -Wstrict-overflow=5
делает это еще более вероятным, так как это самый высокий уровень предупреждения, который поставляется с собственным отказом от ответственности:
этот уровень предупреждения дает очень большое количество ложных срабатываний
Я предлагаю либо обновить ваш компилятор, либо согласиться с тем, что gcc 5.4 даст вам ложный положительный результат.