Solved 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.
-
-
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?