Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Segmentation fault when binding C++ function to QML property



  • Hello!

    I have two C++ classes registered with QML that are instantiated in QML as components.
    I also have a third component that binds a C++ function to a property.

    These three components are instantiated in the order below:

    Component1 [
    	id: comp1
    }
    
    Component2 {
    	id: comp2
            comp1prop: comp1
    }
    
    Component3 {
    	property Component2 comp2prop: comp2
    	property int number : comp2prop.calcNumber()
    }
    

    Component 2 has a pointer to Component1 and has a set function that sets this pointer based on what the property is set to in QML.

    class Component2 : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(Component1* comp1prop READ comp1prop WRITE setComp1prop NOTIFY comp1PropChanged)
    
        int calcNumber() { return comp1prop_->aNumber() }
    
    ...
    private:
        Component1* comp1prop_ = nullptr;
    

    This works fine whenever i explicitly call calcNumber() at some point, but not when it is used in a property binding.
    The program then crashes due to a segmentation fault.

    The answer seems to be that Component2's pointer to Component1 is not yet set, but in my mind this should work because Component 2 is created after Component 1 and I assumed the property, and thus the pointer, would be set then. So when component 3 uses the function in component 2, everhything should already exist.

    What am I missing?
    Is this bad practice? What exactly is bad practice in that case?

    (Just to add: I very recently started working with QML after a long time away from it so everything is a bit hazy ...!)


  • Moderators

    @Obi-Wan
    Hi, I think the property bindings are evaluated before the component is completed, so your comp1_prop_ is still a nullptr. And I don't think anything in QML guarantees order of initialization, but I'm happy to be contradicted by someone on this.

    this should work:

    int calcNumber() { return comp1prop_  ? comp1prop_->aNumber() : 0 }
    


  • @J-Hilk said in Segmentation fault when binding C++ function to QML property:

    Hi, I think the property bindings are evaluated before the component is completed, so your comp1_prop_ is still a nullptr.

    ...

    int calcNumber() { return comp1prop_  ? comp1prop_->aNumber() : 0 }
    

    This seems to be the case, and checking the pointer in C++ first does fix the issue. What also seems to work is doing this in Component3:

    Component.onCompleted: {
            number = Qt.binding(function() {return comp2prop.calcNumber()})
    }
    

    But I'm not sure this is a safe thing to do, specifically because of what you mention:

    And I don't think anything in QML guarantees order of initialization, but I'm happy to be contradicted by someone on this.

    The only thing I can find in the documentation about this is that the order of the onCompleted handlers is undefined, but I struggle to understand the full consequence of this. I think, in coming from pure C++ to QML and C++, I struggle to wrap my head around the structure and order of the code, and the relation between C++ objects that are created in QML as Components. I'm just thinking loudly now, and this is not the place to "figure it all out", but if you have any suggestions I'm all ears.


Log in to reply