XmlListModel causes malloc fail !



  • Hello,

    I'm using QT5.3.
    I'm tying to allocate a large amount of memory (600 to 900 Mb) in a plugin, but can't manage to do it when my QML contains a XmlListModel.
    Yeah, i agree, very strange, so here is a sample code that reproduces the problem. I probably did something wrong, but can't manage to find what.
    (Note: And this is working in QT4 !)

    MyPaintedItem.h
    @
    #ifndef MYPAINTEDITEM_H
    #define MYPAINTEDITEM_H

    #include <QQuickPaintedItem>

    class MyPaintedItem : public QQuickPaintedItem
    {
    Q_OBJECT
    Q_DISABLE_COPY(MyPaintedItem)
    public:
    MyPaintedItem(QQuickItem *parent = 0);
    ~MyPaintedItem();

    virtual     void paint  (QPainter *painter);
    Q_INVOKABLE void doAlloc(int size);
    

    };

    #endif // MYPAINTEDITEM_H
    @

    MyPaintedItem.cpp
    @
    #include <Windows.h>
    #include <QPainter>

    #include "MyPaintedItem.h"

    //--------------------------------------
    MyPaintedItem::MyPaintedItem(QQuickItem *parent)
    : QQuickPaintedItem(parent)
    {
    qDebug() << "[MyPaintedItem::MyPaintedItem] " << GetCurrentThreadId();
    setFlag(ItemHasContents, true);
    //doAlloc(600000000); // This allocation works fine in every cases (i.e. whether XmlListModel present or not in QML file)
    }

    //--------------------------------------
    MyPaintedItem::~MyPaintedItem()
    {
    }

    //--------------------------------------
    void MyPaintedItem::paint(QPainter *painter)
    {
    qDebug() << "[MyPaintedItem::paint] " << GetCurrentThreadId();
    }

    //--------------------------------------
    void MyPaintedItem::doAlloc(int size)
    {
    void* mem;

    qDebug() << "[MyPaintedItem::doAlloc] " << GetCurrentThreadId();
    mem = malloc(size);
    if (mem!=NULL)  {   qDebug() << "--&gt; malloc OK"; free(mem); }
    else            {   qDebug() << "--&gt; malloc KO";            }
    

    }
    //--------------------------------------
    @

    main.qml
    @
    import QtQuick 2.3
    import QtQuick.Window 2.2
    import QtQuick.XmlListModel 2.0

    import Lib.MYPAINTEDITEM 1.0

    Window {
    visible: true
    width: 1280
    height: 1024
    color: "black"

    XmlListModel {
        id: xmlModel
        xml: "<list><item>This i want</item><item>This i want2</item></list>"
        query: "/list/item"
        XmlRole {
            name: "item"
            query: "string()"
        }
    }
    
    ListView {
        width: 200; 
        height: 200
        model: xmlModel
        delegate: Text { color: "White"; text: item }
    }
    
    MyPaintedItem{
        id:myItem
        anchors.fill: parent
    }
    
    MouseArea {
        anchors.fill:parent
        onClicked: {
            console.log("Mouse clicked....")
            myItem.doAlloc(600000000);
        }
    }
    

    }
    @

    --> The allocation in the constructor always succed (whether a XmlListModel is present in my QML or not)
    --> The allocation on mouse clicked fails as soon as the QML file contains a XmlListModel.
    Here are the output I got:
    With XmlListModel present in my QML (whether ListView is present or not has no impact):
    @
    [MyPaintedItem::MyPaintedItem] 2080
    [MyPaintedItem::doAlloc] 2080
    [MyPaintedItem::paint] 2080
    qml: Mouse clicked....
    [MyPaintedItem::doAlloc] 2080
    --> malloc KO
    @

    With XmlListModel (and ListView) commented in my QML:
    @
    [MyPaintedItem::MyPaintedItem] 488
    [MyPaintedItem::doAlloc] 488
    [MyPaintedItem::paint] 488
    qml: Mouse clicked....
    [MyPaintedItem::doAlloc] 488
    --> malloc OK
    @

    Am I doing something wrong, or is there an issue with XmlListModel and memory consumption in QT5 ?

    Another question: From QT5 documentation on QQuickPaintedItem, I thought rendering was done in a separate thread than the main thread, But wherever i call GetCurrentThread or GetCurrentThreadId (Constructor, paint, Setters, Getters, etc...), I get always the same value. I was expecting to get a different ID. Am I wrong ?

    Thank you.



  • Hi,

    I tried to run your example, and I have bad news ... It runs perfectly for me.
    @Starting /home/gabor/build-allocation-Desktop_Qt_5_3_0_GCC_64bit-Debug/allocation...
    QML debugging is enabled. Only use this in a safe environment.
    [MyPaintedItem::MyPaintedItem]
    [MyPaintedItem::doAlloc]
    --> malloc OK
    [MyPaintedItem::paint]
    qml: Mouse clicked....
    [MyPaintedItem::doAlloc]
    --> malloc OK
    qml: Mouse clicked....
    [MyPaintedItem::doAlloc]
    --> malloc OK
    qml: Mouse clicked....
    [MyPaintedItem::doAlloc]
    --> malloc OK
    qml: Mouse clicked....
    [MyPaintedItem::doAlloc]
    --> malloc OK@

    I have used Debian Wheezy, Qt 5.3.0, QtQuick 2.3.

    I do not know if this helps, but I had mysterious allocation failures before, and it usually turned out that i have corrupted the heap at an unrelated pleace in my program ...

    Good luck with this though!

    Gábor


  • Lifetime Qt Champion

    Hi,

    To add to Gábor Angyal, you should run your application through Valgrind



  • First of all, thanks to both of you for your time and help,

    Gábor: I'm in QT5.3.2 (Windows XP32bits 3GB memory), I'll try QT5.3.0 and see if it helps
    Gábor, SGaist: Concerning a potential heap corruption elsewhere in my code, that was also my first idea (And I would have prefer that !), that's why I isolate the problem in a very simple case.
    In this sample, I have nothing else than what's posted upper and:

    @
    #ifndef MYPAINTEDITEM_PLUGIN_H
    #define MYPAINTEDITEM_PLUGIN_H

    #include <QQmlExtensionPlugin>

    class MyPaintedItemPlugin : public QQmlExtensionPlugin
    {
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.QT.QQmlExtensionInterface")

    public:
    void registerTypes(const char *uri);
    };

    #endif // MYPAINTEDITEM_PLUGIN_H
    @

    And:

    @
    #include "MyPaintedItem_plugin.h"
    #include "MyPaintedItem.h"

    #include <qqml.h>

    void MyPaintedItemPlugin::registerTypes(const char *uri)
    {
    // @uri Lib.MYPAINTEDITEM
    qmlRegisterType<MyPaintedItem>(uri, 1, 0, "MyPaintedItem");
    }
    @

    With this sample, I'm able to allocate up to more than 900 Mb in the constructor, on my computer,
    but this amount falls down to 500 Mb if the allocation is done after application setup (i.e. on mouse clicked).
    I can't imagine XmlListModel uses about 400Mb to parse :
    "<list><item>This i want</item><item>This i want2</item></list>".

    Gábor, could you try something for me, please ?:
    I saw you were on a 64 bits plateform, this and the amount of memory you have can help.
    Could you try to see how much you're able to allocate in the constructor, and once you reached this amount, remove the allocation from the constructor,
    and try to allocate this amount, minus let's say 200 or 300 Mb in MouseArea.onClicked.
    Does it still run perfectly on your computer ?
    Does the use of XmlListModel make this amount fall by about 400Mb ?

    SGaist: I'll try Valgrind on my sample and give you feedback. (but I don't know what could be changed on my simple plugin that is only doing a simple allocation...)



  • I have the same problem in QT5.3.0
    Something happened between QT4.8.3 and QT5.3.0.



  • I will try that for you, as soon as I can, but unfortunatelly I am ~900 km away from my work computer. I will be back around the 9th of January.

    Until that I wish you a Merry Christmass and a Happy New Year!



  • No problem,
    Thank you for your help,
    I also wish a merry christmas and happy new year to you, and those who will read this thread ;-)


Log in to reply
 

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