Cannot destroy C++ Object in QML



  • Hi,

    in my code I want to delete an object that I pass to QtQuick in order to prevent a memory leak. However, I fail to be able to call 'deleteLater' from QML. It does not get exposed as a slot and when I create my own slot that destroys the object I get the error message "Invalid attempt to destroy() an indestructible object". Is there a way I can fix this?



  • How was the object created?
    It may be easier to use QQmlEngine::setObjectOwnership() to assign the object to the QML engine, and allow garbage collection to handle it.



  • Thanks for your reply!

    The object is created on the heap in C++. I'd prefer a solution that would not require to have it handled by JavaScript.
    My use-case is this: The object wraps a task. If it fails the user is prompted (by a QML MessageDialog) whether there should be a retry (using the same object) or whether it should be canceled. In case of canceling I need to destroy the object. Is it possible to transfer ownership on the QML-side?


  • Moderators

    @antipattern said:

    I'd prefer a solution that would not require to have it handled by JavaScript.

    Is it possible to transfer ownership on the QML-side?

    before that you have to decide what you want.



  • I'd like a way to prevent a memory leak. If possible I'd be great to be able to call the descructor, if not transfering the resposnibility to the GC is also fine.


  • Moderators

    @antipattern
    than @jeremy_k gave you the solution already



  • Explicitly managing the lifetime of a C++ object used by QML is possible, but be aware that extra code is required on the QML side to detect invalid objects. Failure to do so can lead to javascript exceptions, application crashes, and the general variability of undefined behavior through the access of stray pointers.

    Things such as:

    property int prop: object.value
    

    become

    property int prop: isValid(object) ? object.value : -1
    


  • I have trouble with both solutions. In the documentation I only found how to change the ownership of an object from C++ and not from JavaScript. Is this the only way?

    Also, I didn't manage to explicitly manage the object's life-cycle, does the ownership need to be transfered first? I tried using the JavaScript delete.



  • There isn't an API to explicitly change the ownership from javascript.

    The documentation briefly covers the topic at http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership.

    Is the code sufficiently brief to post here?



  • Here are the important bits of my code:
    main.qml

    // ...
    EntryModel {
    	id: entryModel
    	onError: {
    		jobFailedDialog.informativeText = errorMessage
    		jobFailedDialog.accepted.disconnect(failedJob.retry) // workaround for missing Qt::UniqueConnection in QML
    		jobFailedDialog.accepted.connect(failedJob.retry)
    		jobFailedDialog.rejected.disconnect(failedJob.deleteLater)
    		jobFailedDialog.rejected.connect(failedJob.deleteLater)
    		jobFailedDialog.open()
    	}
    }
    
    MessageDialog {
    	id: jobFailedDialog
            // ...
    	standardButtons: StandardButton.Retry | StandardButton.Cancel
    }
    

    EntryModel:

    class EntryModel : public QAbstractListModel
    {
        // ...
    signals:
        void error(Job *failedJob, QString errorMessage);
    
    public slots:
        void gatewayError(std::string error_string) {
            qWarning() << "Error: " << QString::fromStdString(error_string);
            emit error(static_cast<Job*>(QObject::sender()), QString::fromStdString(error_string));
        }
        // ...
    };
    

    Job:

    class Job : public QObject
    {
         // ...
    
    signals:
        void error(const std::string &error_string);
    
    public slots:
        void retry() { if (executed_) { executed_ = false; execute(); } }
        
        // ...
    };
    

    The jobs are executed from the EntryModel and their error-signal is connected to EntryModel::gatewayError. This signal triggers the jobFailedDialog.
    I left out the irrelevant bits, I hope the code is sufficient to clarify my problem.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.