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

Out of memory in text binding



  • Hello, everybody)
    I'm writting a FB2-reader. So, I need to display a huge string of about 1 or 2 million characters.
    I have a C++ class which has a public slot QString parseBook(const QString & fileName) that converts a FB2-file to HTML. I know that this method works correctly.
    I have a text block to display a FB2-book converted to HTML. And I'm trying to set my huge string to this text block.

    Text {
            id: bookView
            x: 236
            y: 83
            width: 630
            height: 384
            text: fb2Reader.parseBook("") // I'm trying to call parsing method
            textFormat: Text.RichText
            font.pixelSize: 12
        }
    

    As a result of these actions, I get a runtime error and the following messages in the application output console:

    D3D11 WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: Live Producer at 0x006C7E94, Refcount: 20. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x006E37C8, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498A8838, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498AE744, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498B11F4, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498B132C, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498B1514, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x49896F64, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498970C4, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498B3404, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498B3C7C, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x537B0F30, Refcount: 2. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x49854C44, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x49894354, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x537AEE44, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x49853434, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498954F4, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x537B21F4, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x498549DC, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x537B3324, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x537B34AC, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x49854EAC, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x49852A94, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: 	Live Object at 0x49852CFC, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
    D3D11 WARNING: Live                         Object :     23 [ STATE_CREATION WARNING #0: UNKNOWN]
    DXGI WARNING: Live Producer at 0x00699068, Refcount: 5. [ STATE_CREATION WARNING #0: ]
    DXGI WARNING: 	Live Object at 0x0069B7E8, Refcount: 3. [ STATE_CREATION WARNING #0: ]
    DXGI WARNING: Live                         Object :      1 [ STATE_CREATION WARNING #0: ]
    Out of memory  in c:\Users\qt\work\install\include/QtCore/qvarlengtharray.h, line 372
    terminate called without an active exception
    Out of memory  in c:\Users\qt\work\install\include/QtCore/qvector.h, line 563
    terminate called without an active exception
    

    Help me, please( I don't understand why this happened, because I have similar app written via QtWidgets and there I don't have any problems transferring a huge string from method to QTextBrowser.



  • @ODUHO4KA

    Just as a Test Case, could you try to use TextEdit Component instead of Text ? i'm not sure if Text component have the same limitation of QLabel from cpp in relation to display large amount of text.
    Note: QTextBrowser Inherits QTextEdit (from cpp)



  • Maybe I am just guessing here, but is it somehow creating the memory on the stack instead of the heap?

    Anyway, Text uses "string" type for "text" property so should theoretically hold a couple of gigs of data:
    https://forum.qt.io/topic/10302/what-is-the-maximum-length-of-string-that-qstring-object-can-hold



  • @KillerSmath , @fcarney , thanks for your replies!) I've changed the Text Component to this element:

    ScrollView {
            id: view
    
            anchors.left: parent.left
            anchors.leftMargin: 236
            anchors.top: parent.top
            anchors.topMargin: 101
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 13
            anchors.right: parent.right
            anchors.rightMargin: 13
    
            TextArea {
                id: bookView
                width: 631
                height: 366
                text: fb2Reader.book
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
                smooth: false
                readOnly: true
                renderType: Text.NativeRendering
                anchors.topMargin: 0
                anchors.leftMargin: 0
                anchors.rightMargin: 0
                anchors.bottomMargin: 0
                anchors.fill: parent
                textFormat: Text.RichText
            }
        }
    

    I have this code now:

    //main.cpp
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        FB2Reader reader;
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("fb2Reader", &reader);
        engine.load(QUrl(QStringLiteral("qrc:/qml/desktop/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    
    // fb2reader.h
    
    class FB2Reader : public QObject
    {
        Q_OBJECT
    
        Q_PROPERTY(QString book READ book NOTIFY bookChanged);
    
        QString m_book = "";
    
    public:
        FB2Reader() = default;
    
        QString book() const;
    
    public slots:
        void parseBook(const QString & fileName);
    
    signals:
        void bookChanged();
    
    };
    

    I just change the m_book string in my parseBook slot (something just like this:

    m_book.append("<span> " + sr.text().toString() + "</span>");
    

    ) and I emit the bookChanged signal after that.

    I think that I have "out of memory" warning because of transferring huge data from C++ to QML via binding.

    Does anybody know the reasons why this happened? I really need your help!(



  • @ODUHO4KA said in Out of memory in text binding:

    Does anybody know the reasons why this happened?

    So with the changes you made it is still giving you the memory error?



  • @fcarney
    Unfortunately, yes



  • What if you set it to a property you create rather than the text property of the TextArea:

    property string bigtextprop: fb2Reader.book
    

    This would test if it is an issue with the "string" datatype in qml versus the actual widget itself.

    Either way, if you cannot load the entire file you may need to page it. Yeah, that kinda sucks.



  • @fcarney ok, I'll try it later. Thanks)



  • I was curious so I did a test:
    main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QVector>
    #include <QDebug>
    #include <QQmlContext>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
    
        QString bigString;
        QString az;
        for(auto ch = 'a'; ch <= 'z'; ++ch){
            az += ch;
        }
    
        for(auto i=0; i < 1000*100; ++i){
            if(i%2 == 0){
                bigString += "<div style=\"color:#ff0000;\">" + az + "</div>";
            }else{
                bigString += "<div style=\"color:#0000ff;\">" + az + "</div>";
            }
    
            bigString += '\n';
        }
    
        qInfo() << QLocale(QLocale::English).toString(bigString.length());
    
        engine.rootContext()->setContextProperty("bigString", bigString);
    
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
        engine.load(url);
    
        return app.exec();
    }
    

    main.qml:

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 1.4
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Large Text Editing")
    
        property string extText: bigString
    
        Button {
            id: but_loadtext
            width: 50
            height: 20
            text: "load"
    
            onClicked: {
                tarea.text = Qt.binding(function(){ return extText;})
            }
        }
    
        TextArea {
            id: tarea
            width: parent.width
            anchors.top: but_loadtext.bottom
            anchors.bottom: parent.bottom
            text: "Some text"
            textFormat: TextEdit.RichText
        }
    }
    

    The output of the qInfo statement is "6,100,000" so it was 6 megabytes of data.

    The button does a binding of the property extText to the TextArea text property. This takes about 5 seconds and seems to work. The responsiveness is pretty crappy. At 1 meg or less the responsiveness is much better. I am not getting any memory errors. I did try larger at 27 megs, but it was taking forever to load. From a responsiveness point of view I would go with like 500K to 1 meg max. So if your file is larger I would go with paging. How big is your file?


Log in to reply