首页 > 解决方案 > [-Wstrict-overflow] 在这里是什么意思?

问题描述

最小的应用程序:

测试项目.pro:

QT       += core gui widgets
CONFIG   += C++11

QMAKE_CXXFLAGS_RELEASE -= -O
QMAKE_CXXFLAGS_RELEASE -= -O0
QMAKE_CXXFLAGS_RELEASE -= -O1
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE *= -O3
QMAKE_CXXFLAGS_RELEASE -= -Os
QMAKE_CXXFLAGS_RELEASE -= -Ofast

TARGET   = TestProject
TEMPLATE = app

SOURCES += main.cpp\
           mainwindow.cpp

HEADERS += mainwindow.h

主.cpp:

#include <mainwindow.h>
#include <QApplication>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

主窗口.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QObject>
#include <QStack>

class Other : public QObject
{
    Q_OBJECT
public:
    explicit Other(QObject* parent = 0);
    virtual ~Other();

    void test();

private:
    QStack<int> myStack;
};

//--------------------------------------------------------------------------------------------------

#include <QMainWindow>
#include <QPushButton>
#include <QTextEdit>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget* parent = 0);
    virtual ~MainWindow();
};

#endif // MAINWINDOW_H

主窗口.cpp:

#include "mainwindow.h"

Other::Other(QObject* parent) :
    QObject(parent)
{}

Other::~Other()
{}

void Other::test()  //warning on this line
{
    myStack.pop();  //but not when this line is commented
}

//--------------------------------------------------------------------------------------------------

MainWindow::MainWindow(QWidget* parent) :
    QMainWindow(parent)
{
    (new Other(this))->test();
}

MainWindow::~MainWindow()
{}


编译g++ -O3 -Wall给出了这个警告:

...TestProject/mainwindow.cpp:10: warning: assuming signed overflow does not occur when assuming that (X - c) <= X is always true [-Wstrict-overflow]
 void Other::test()  //warning on this line
      ^

编译g++ -O2 -Wall没有。

这个问题是有道理的,因为它是有条件的,但我没有得到它的条件。我在一个函数本身上得到它。

我想使用更积极的优化,但如果可以的话,仍然可以干净地编译。有什么奇怪的事情QStack吗?


更新:

我仍然不知道在这种情况下警告应该是什么意思,但我找到了一种方法来摆脱它。

我复制了代码qstack.h并将其粘贴到我自己的函数中,然后调用它而不是内置的QStack::pop()

void Other::pop()  //warning on this line
{
    Q_ASSERT(!myStack.isEmpty());
    int t = myStack.data()[myStack.size() - 1];
            myStack.resize(myStack.size() - 1);
    return t;
}

仍然有警告,但它已移至自定义pop()功能。

然后我玩了一下,发现操作缓存myStack.size() - 1resize杀死警告,但前提是它在提取之前完成data()

void Other::pop()  //no warning
{
    Q_ASSERT(!myStack.isEmpty());
    int size = myStack.size() - 1;
    int t = myStack.data()[myStack.size() - 1];
            myStack.resize(size);
    return t;
}

对这两个操作使用缓存值也是无警告的。

所以这可能是摆脱它的几种方法之一,但有谁知道它为什么会发生在这里?

标签: qtg++gcc-warning

解决方案


警告告诉您编译器没有检查减法的结果是否为负。

为什么这在这个特定的行中很重要?

myStack.data()[myStack.size() - 1];

因为您正在使用减法运算的结果索引数组(实际上使用指针变量,来自data()函数,返回 a T*),这可能会导致负数,这通常是您不想要的。

当您进行减法并将其移动到新变量时,编译器会看到您正在使用变量直接索引数组int,而不是减法的结果,因此如果传递的变量为负数,它不会再发出警告.


关于您的评论,您正在使用该resize功能的缓存数据。我不太确定为什么会发生这种情况,但我想这可能与-O3编译器中启用以下标志有关:

-finline-functions 

有关详细信息,请参阅http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html 。

此标志启用所有内联函数优化。由于您使用的是所有模板化类,编译器可能会内联所有涉及的函数,缓存一些结果,并且在某处优化签名溢出。大概在函数中的if句子中resize

template <typename T>
void QVector<T>::resize(int asize)
{
    int newAlloc;
    const int oldAlloc = int(d->alloc);
    QArrayData::AllocationOptions opt;

    //Here, asize will be replaced with d->size - 1 after all the inlining.
    //So the compiler is assuming that d->size - 1 will not overflow, 
    //  because of undefined behaviour, 
    //  instead of thinking that it may wrap.
    if (asize > oldAlloc) { 
        newAlloc = asize;
        opt = QArrayData::Grow;
    } else {
        newAlloc = oldAlloc;
    }
    reallocData(asize, newAlloc, opt);
}

但这只是一个猜测。


推荐阅读