C++ Qt5.7的deleteLater()是否取决于操作系统?
大家好,我在代码中发现了一个bug,那就是: 我有一个指向QLocalSocket的指针列表,在析构函数中,我用下面的代码关闭并删除它们C++ Qt5.7的deleteLater()是否取决于操作系统?,c++,windows,qt,qt5,C++,Windows,Qt,Qt5,大家好,我在代码中发现了一个bug,那就是: 我有一个指向QLocalSocket的指针列表,在析构函数中,我用下面的代码关闭并删除它们 for ( int i = 0; i < localSocketsList.size(); i++ ) { if ( localSocketsList.at(i) != NULL ) { localSocketsList.at(i)->close(); localSocketsList.at(i)-&
for ( int i = 0; i < localSocketsList.size(); i++ )
{
if ( localSocketsList.at(i) != NULL )
{
localSocketsList.at(i)->close();
localSocketsList.at(i)->deleteLater();
}
}
for(int i=0;iclose();
localSocketsList.at(i)->deleteLater();
}
}
错误在于,我之前用套接字的disconnected()信号连接了一个插槽,该插槽也用代码删除了它们:
QMutableListIterator<QLocalSocket *> iterator(localSocketsList);
while( iterator.hasNext() )
{
QLocalSocket * currentLocalSocket = iterator.next();
if ( currentLocalSocket -> state() == QLocalSocket::UnconnectedState )
{
currentLocalSocket -> deleteLater();
iterator.remove();
}
}
QMutableListIterator迭代器(localSocketsList);
while(iterator.hasNext())
{
QLocalSocket*currentLocalSocket=iterator.next();
如果(currentLocalSocket->state()==QLocalSocket::UnconnectedState)
{
currentLocalSocket->deleteLater();
iterator.remove();
}
}
好的,现在你可以看到错误,我尝试删除一个指针两次,结果崩溃了。但是,我花了一段时间才发现这个错误,因为我没有在Windows10中观察到崩溃,只有在Windows7中
问题是:Qt5.7的deleteLater()函数是否因操作系统而异?这个问题不应该出现在所有的平台上,因为它是C++运行时错误?< /P>
也许这取决于Qt如何安排作业(我的意思是,在发送信号之前完成for循环)?在这种情况下,作业的时间表是否取决于操作系统?这不应该几乎是“随机的”吗
谢谢大家在控件返回到事件循环之前多次调用
deleteLater
是有效的:
#include <QtCore>
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
auto obj = new QObject;
obj->deleteLater();
obj->deleteLater();
connect(obj, &QObject::destroyed, []{ qApp->quit(); });
return app.exec();
}
您确定它发生在同一事件循环周期中吗?在同一个周期中多次调用它是可以的,因为挂起的事件将被删除,但是如果它不是同一个周期,您将得到崩溃,因为它是一个悬空指针。有趣的是,我不知道我以后可以在同一个周期中调用Delete两次。但是为什么在Windows10中我没有错误?谢谢你的回答。你说的有道理,可能错误是“删除”了列表。但即便如此,为什么我没有在窗口10中看到这个错误?我只是在尝试Windows 7时发现的,因为您的代码是异步的,断开连接通知可能会在不同的时间到达。我很确定Windows版本只会改变发生此错误的概率-如果您对其进行了足够的测试(数百万甚至数十亿个连接),您将在任何版本的Windows上发生此错误。非常感谢;)找出问题出在列表上,而不是双重deleteLater()对我帮助很大
// https://github.com/KubaO/stackoverflown/tree/master/questions/qobject-pointer-list-43986348
#include <QtCore>
class PointerListData : public QObject, public QSharedData {
Q_OBJECT
public:
QVector<QObject*> list;
void removed() { list.removeAll(sender()); }
void connect(QObject* obj) {
QObject::connect(obj, &QObject::destroyed, this, &PointerListData::removed);
}
void disconnect(QObject* obj) {
QObject::disconnect(obj, &QObject::destroyed, this, &PointerListData::removed);
}
};
template <typename T> class PointerList {
protected:
QExplicitlySharedDataPointer<PointerListData> d;
public:
PointerList() : d(new PointerListData) {}
PointerList(const PointerList &other) : d(other.d) {}
PointerList(PointerList && other) : d(std::move(other.d)) {}
void append(T* obj) {
auto connect = !contains(obj);
d->list.append(obj);
if (connect)
d->connect(obj);
}
PointerList & operator<<(T* obj) {
append(obj);
return *this;
}
int removeAll(T* obj) {
auto n = d->list.removeAll(obj);
if (n)
d->disconnect(obj);
return n;
}
bool contains(T* obj) const {
return d->list.contains(obj);
}
void clear() {
for (auto obj : d->list)
d->disconnect(obj);
d->list.clear();
}
void moveToThread(QThread* thread) { d->moveToThread(thread); }
bool isEmpty() const { return d->list.isEmpty(); }
int size() const { return d->list.size(); }
using iterator = T**;
using const_iterator = const T**;
iterator begin() { return iterator(d->list.data()); }
iterator end() { return iterator(d->list.data() + d->list.size()); }
const_iterator begin() const { return const_iterator(d->list.constData()); }
const_iterator end() const { return const_iterator(d->list.constData() + d->list.size()); }
constexpr const PointerList& crange() const noexcept { return *this; }
// see http://stackoverflow.com/q/15518894/1329652
};
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
PointerList<QMimeData> list;
{
QMimeData a;
QMimeData b;
list << &a << &b;
auto list2 = list;
Q_ASSERT(list2.size() == 2);
for (auto obj : list.crange())
qDebug() << obj;
}
Q_ASSERT(list.isEmpty());
}
#include "main.moc"