2012-12-12 5 views
19

Die neue Qt5-Signale und Slots-Syntax ermöglicht es uns, Signale nicht nur an Slots, sondern auch an alte Funktionen und Funktoren/Lambdas zu verbinden. Nun ist das Problem, dass Lambdas wesentliche Objekte mit() Operator sind, und wenn Sie Signale mit ihnen verbinden, werden sie irgendwo in qt internen Klassen kopiert. Und wenn Sie das Signal von diesem Funktor trennen, bleibt es in qt internes. Ich verstehe nicht, ist das ein normales Verhalten? Oder gibt es eine Möglichkeit, diese funktionalen Objekte nach der Trennung zu zerstören?Qt5 neues Signal zu Lambda-Verbindungen Speicherleck

Hier ist ein Beispiel:

//example 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 

    QTimer* timer = new QTimer(); 

    QSharedPointer<QMetaObject::Connection> connection(new QMetaObject::Connection()); 

    //functor is created and gets copied inside qt internals, connection variable is captured 
    //inside the functor 

    *connection.data() = QObject::connect(timer, &QTimer::timeout, [=] 
    { 
     qDebug() << "disconnected"; 
     QObject::disconnect(*connection.data()); 
    }); 

    timer->start(10000); 

    return a.exec(); 
} 

//example 

Jetzt, als ich zählt starke Referenz der Verbindung variabel zu buchen, nach der Schlitz Trennung, es 2 bleibt, was bedeutet, dass das Funktor Objekt selbst noch am Leben ist und gut, obwohl es Es nützt mir jetzt nichts. Vermisse ich etwas?

+0

Was, wenn Sie den Timer zerstören passiert? –

+0

Hatte das auch gedacht, aber der Referenzzähler bleibt immer noch 2 =/ – Sigil

+0

Der einzige Weg geht zu 1, wenn ich die Verbindungsvariable nicht in diesem '* connection.data() =' Teil ablege und den Timer lösche. Was immer noch sehr seltsam ist. – Sigil

Antwort

7

Das Beispiel ist überentwickelt (warum sollte man einen QSharedPointer verwenden? Warum sollte man ihn nach Wert erfassen?). Aber in der Tat gibt Qt das funktor Objekt aus.

Der Punkt ist, dass die interne Verbindungsliste wird einfach als schmutzig markiert, und nicht gelöscht, bis entweder der Absender gelöscht oder ein neues Signal angeschlossen ist (siehe die Verwendungen von cleanConnectionLists).

schob ich ein paar Patches, die dieses Verhalten beheben sollte: https://codereview.qt-project.org/#change,42976 und 42979

+1

Nun ja, ich weiß, dass es ein wenig überentwickelt aussehen könnte, aber ich brauchte diesen geteilten Zeiger, um einfach die Anzahl der Referenzen darauf überwachen zu können, um zu sehen, ob das Funktorobjekt noch am Leben ist, und ich habe ein echtes Projekt, bei dem sich ähnliche Logik nicht in der Hauptfunktion befindet, also kann ich dort nicht einfach Verbindung durch Referenz erfassen. – Sigil