2017-05-15 5 views
0

Guten Tag alle, ich habe einen Fehler in meinem Code entdeckt, das heißt:Ist deleteLater() von Qt5.7 vom Betriebssystem abhängig?

Ich habe eine Liste von Zeigern auf QLocalSocket und in der destructor Ich schließe und löschen Sie sie mit dem folgenden Code

for (int i = 0; i < localSocketsList.size(); i++) 
{ 
    if (localSocketsList.at(i) != NULL) 
    { 
     localSocketsList.at(i)->close(); 
     localSocketsList.at(i)->deleteLater(); 
    } 
} 

der Fehler war, dass ich vorher einen Schlitz mit dem getrennten verbunden() Signal der Buchsen und die Schlitz sich mit dem Code auch löschen:

QMutableListIterator<QLocalSocket *> iterator(localSocketsList); 
while(iterator.hasNext()) 
{ 
    QLocalSocket * currentLocalSocket = iterator.next(); 
    if (currentLocalSocket -> state() == QLocalSocket::UnconnectedState) 
    { 
     currentLocalSocket -> deleteLater(); 
     iterator.remove(); 
    } 
} 

Ok jetzt können Sie den Fehler sehen, die ich versuche, lösche einen Zeiger twic e und ich haben einen Unfall. ABER, es dauerte eine Weile, um diesen Fehler zu erkennen, weil ich keinen Absturz in Windows 10 beobachtet, nur in Windows 7.

Die Frage ist: Gibt es einen Unterschied in der deleteLater() -Funktion von Qt5.7 abhängig des operativen Systems? Sollte dieses Problem nicht auf allen Plattformen auftreten, da es sich um einen C++ Laufzeitfehler handelt?

Vielleicht hängt etwas davon ab, wie Qt den Job plant (ich beende den Zyklus vor dem Senden der Signale). In diesem Fall ist der Zeitplan der Jobs abhängig vom Betriebssystem? Sollte das nicht fast "zufällig" sein?

Vielen Dank allen

+0

Sind Sie sicher, dass es im selben Ereignisschleifenzyklus passiert? Es ist OK, es mehrmals im selben Zyklus aufzurufen, da ausstehende Ereignisse entfernt werden, aber wenn es nicht derselbe Zyklus ist, werden Sie einen Absturz bekommen, weil es ein ungeeigneter Zeiger ist. – dtech

+0

Interessant, ich wusste nicht, dass ich deleteLater zweimal im selben Zyklus aufrufen könnte. Aber warum in Windows 10 habe ich keinen Fehler? – n3mo

Antwort

0

Es gilt deleteLater mehrere Male vor der Steuerung kehrt zu der Ereignisschleife aufzurufen:

#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(); 
} 

So scheint es mir, dass Ihr Problem nicht in Berufung auf deleteLater mehrere ist Zeiten, aber Iterieren über eine Sammlung von Objekten, die zerstört wurden. Die localSocketList ist nicht bewusst, dass die Sockets gelöscht werden und enthält Zeiger.

Es gibt eine einfache Abhilfe dafür - verwenden Sie eine Liste, die Objekte gelöscht wird. Der Einfachheit halber ist die folgende Liste explizit freigegeben, d. H. Jede ihrer Kopien bezieht sich auf das gleiche Objekt (das sind auch JavaScript-Semantiken, wenn Sie damit vertraut sind).

// 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" 
+0

Danke für die Antwort. Es macht Sinn, was du sagst, wahrscheinlich ist der Fehler das "Entfernen" der Liste. Aber warum habe ich diesen Fehler in Windows 10 nicht gesehen? Ich entdeckte es nur, wenn ich Windows 7 versuchte – n3mo

+0

Weil Ihr Code asynchron ist und die Benachrichtigung über die Trennung möglicherweise zu einem anderen Zeitpunkt eintreffen. Ich bin mir ziemlich sicher, dass die Windows-Version nur die Wahrscheinlichkeit ändert, dass dieser Fehler auftritt - wenn Sie es genug getestet haben (Millionen oder sogar Milliarden von Verbindungen), würden Sie es bei jeder Version von Windows auftreten lassen. –

+0

Vielen Dank;) herauszufinden, dass das Problem war die Liste und nicht die doppelte deleteLater() hat mir sehr geholfen. ;) – n3mo

Verwandte Themen