2016-07-26 19 views
0

Meine Qt Quick-Anwendung unter Windows erlebt einen sehr seltsamen Absturz.Qt Quick Windows App stürzt ab, wenn C++ versucht, auf das Element (im Bereich) eines Vektors zuzugreifen

Ich habe eine QObject abgeleitete C++ - Klasse namens QObjectVector, die QML-Seite Zugriff auf QObject-Zeiger in einem Container ermöglicht. Auf der QML-Seite habe ich eine Reihe von Schaltflächen, die Namen von Objekten in diesem Container anzeigen. Wenn ich das Mausrad scrolle, aktualisiere ich die currentItem Eigenschaft jeder Schaltfläche manuell.

Merkwürdigerweise und nur manchmal nach einer unberechenbar Anzahl von schnellen Scrollen, stürzt das Programm (funktioniert nicht). Nach dem Debugging habe ich festgestellt, dass der Absturz auftritt, wenn die at Funktion Zugriff m_data[i]. Ich habe sichergestellt, dass i innerhalb des gültigen Bereichs [0, m_data.size()] ist, also ist es kein Index-out-of-range-Fehler. Meine Vermutung ist, dass die QML-Engine irgendwie meine Objekte auf dem Heap löscht, wenn ich versuche, Speicher zu verwalten.

QObjectVector.h

#pragma once 

#include <QObject> 
#include <QVector> 

#include "Types.h" 

namespace LPP 
{ 
    class QObjectVector : public QObject 
    { 
     Q_OBJECT 

     Q_PROPERTY(Int size READ size NOTIFY sizeChanged) 

    public: 
     explicit QObjectVector(); 
     virtual ~QObjectVector(); 

     Int size(); 
     Q_INVOKABLE QObject* at(Int); 
     void push(QObject*); 
     void remove(Int); 
     void remove(QObject*); 

     QVector<QObject*> &getData(); 

     bool deleteChildrenOnDestroy; 

    private: 
     QVector<QObject*> m_data; 

    signals: 
     void sizeChanged(); 

    public slots: 
    }; 
} 

QObjectVector.cpp

... 
    QObject* QObjectVector::at(Int i) 
    { 
     qDebug() << "size: " << this->m_data.size(); 
     for (int i = 0; i < this->m_data.size(); i++){ 
      qDebug() << "i: " << i << " item: "; 
      //when I scroll rapidly, crash happens here when I trace objects in vector 
      qDebug() << this->m_data[i]; 
     } 
     qDebug() << "returning."; 
     return (i >= 0 && i < this->m_data.size()) ? this->m_data[i] : nullptr; 
    } 
.... 

ButtonContainer.qml

.... 
    //this function is called when I scroll mouse wheel. 
    //itemList contains list of Buttons 

    function refreshDisplay() { 
     var i, j = 0; 

     for (i = 0; i < itemList.length; i++){ 
      itemList[i].visible = itemList[i].enabled = false; 
     } 

     var start = Utils.clamp(Math.floor(scrollView.flickableItem.contentY/(itemHeight + itemVSpacing)), 0, currentFolder.size); 
     var end = Utils.clamp(Math.ceil((scrollView.flickableItem.contentY + scrollView.flickableItem.height)/(itemHeight + itemVSpacing)), 0, currentFolder.size); 

     var item; 

     for (i = start; i < end; i++){ 
      if (j >= itemList.length){ 
       itemList.push(tableItem_comp.createObject(tableArea)); 
      } 

      itemList[j].visible = itemList[j].enabled = true; 

      item = currentFolder.at(i); 
      itemList[j].currentItem = item; 
      j++; 
     } 
    } 
.... 

Button.qml

.... 
    property var currentItem: null; 

    anchors.left: parent.left 
    anchors.right: parent.right 

    SimpleButton { 
     id: button 
     width: 100 
     height: 50 
     text: currentItem.name; 
     onClicked: { 
      viewer.select(currentItem); 
     } 
    } 
.... 

Dieses Problem ist sehr seltsam und unberechenbar, und die Lösung ist sehr wichtig für die Entwicklung meiner App, bitte also bitte, jede Hilfe wird geschätzt.

Vielen Dank!

Tommy

+3

Könnten Sie bitte Beschreibungen entfernen und stattdessen tatsächliche Codes veröffentlichen?Angabe, wo der Fehler ist in einem [MCVE] –

Antwort

1

Dies liegt daran, die Objekte Sie Rückkehr von der QML-Engine gehören, und kann daher Müll jederzeit abgeholt werden.

Try

QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership) 

auf jedem Objekt aufrufen, bevor es zu QML zurückgegeben wird (zum Beispiel, wenn es aufgebaut).

Siehe this section der Dokumentation:

Wenn Daten von C++ übertragen auf QML, das Eigentum an den Daten bleibt immer mit C++. Die Ausnahme von dieser Regel ist, wenn ein QObject von einem expliziten C++ - Methodenaufruf zurückgegeben wird: In diesem Fall übernimmt die QML-Engine das Eigentum des Objekts, es sei denn, das Eigentum des Objekts wurde explizit auf C++ festgelegt, indem QQmlEngine :: setObjectOwnership() mit QQmlEngine :: CppOwnership angegeben.

Darüber hinaus respektiert die QML-Engine die normale QObject-Parent-Ownership-Semantik von Qt C++ - Objekten und übernimmt niemals die Eigentümerschaft einer QObject-Instanz, die bereits übergeordnete Elemente besitzt.

+1

Alternativ können die Objekte mit einem Elternteil konstruiert werden – wasthishelpful

+0

Wow, vielen Dank! Übrigens, das Problem, dem ich begegnete, war es wegen der Tatsache, dass meine C++ - Objekte Müll sammelten? EDIT: habe gerade deine Bearbeitung gesehen. – TommyX

+1

Ja; aktualisierte die Antwort, um das zu berücksichtigen. – Mitch