[-Wstrict-overflow] 在这里是什么意思?
What does [-Wstrict-overflow] mean here?
最小应用程序:
TestProject.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
main.cpp:
#include <mainwindow.h>
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.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
mainwindow.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
编译不会。
This question 是有道理的,因为它是有条件的,但我不是有条件的。我正在通过函数本身获取它。
我想使用更积极的优化,但如果可以的话仍然可以干净地编译。 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()
函数。
然后我玩了一下,发现为 resize
操作缓存 myStack.size() - 1
会消除警告,但前提是它在提取 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;
}
对这两个操作使用缓存值也没有警告。
所以这可能是摆脱它的几种方法之一,但是有人知道为什么它会出现在这里吗?
警告告诉您编译器没有检查减法结果是否为负。
为什么这在这一行很重要?
myStack.data()[myStack.size() - 1];
因为您正在使用减法运算的结果索引数组(实际上使用指针变量,来自 data()
函数,returns a T*
)可能会产生负数,这通常是您不想要的结果。
当您进行减法并将其移至新变量时,编译器会发现您是直接使用 int
变量索引数组,而不是减法的结果,因此它不会如果传递的变量是否为负,则不再发出警告。
关于您的评论,您正在使用 resize
函数的缓存数据。我不太确定为什么会发生这种情况,但我想这可能与编译器在 -O3
中启用以下标志有关:
-finline-functions
有关详细信息,请参阅 http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html。
此标志启用所有内联函数优化。由于您使用的是所有模板化 类,编译器可能会内联所有涉及的函数,缓存一些结果并在某处优化签名溢出。大概在resize
函数中的if
句中:
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);
}
但这只是猜测。
最小应用程序:
TestProject.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
main.cpp:
#include <mainwindow.h>
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.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
mainwindow.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
编译不会。
This question 是有道理的,因为它是有条件的,但我不是有条件的。我正在通过函数本身获取它。
我想使用更积极的优化,但如果可以的话仍然可以干净地编译。 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()
函数。
然后我玩了一下,发现为 resize
操作缓存 myStack.size() - 1
会消除警告,但前提是它在提取 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;
}
对这两个操作使用缓存值也没有警告。
所以这可能是摆脱它的几种方法之一,但是有人知道为什么它会出现在这里吗?
警告告诉您编译器没有检查减法结果是否为负。
为什么这在这一行很重要?
myStack.data()[myStack.size() - 1];
因为您正在使用减法运算的结果索引数组(实际上使用指针变量,来自 data()
函数,returns a T*
)可能会产生负数,这通常是您不想要的结果。
当您进行减法并将其移至新变量时,编译器会发现您是直接使用 int
变量索引数组,而不是减法的结果,因此它不会如果传递的变量是否为负,则不再发出警告。
关于您的评论,您正在使用 resize
函数的缓存数据。我不太确定为什么会发生这种情况,但我想这可能与编译器在 -O3
中启用以下标志有关:
-finline-functions
有关详细信息,请参阅 http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html。
此标志启用所有内联函数优化。由于您使用的是所有模板化 类,编译器可能会内联所有涉及的函数,缓存一些结果并在某处优化签名溢出。大概在resize
函数中的if
句中:
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);
}
但这只是猜测。