Details
-
Bug
-
Resolution: Fixed
-
P3: Somewhat important
-
5.3.2
-
None
-
1f39b8ba2745f2b9ff462d40f6b0ca473c94484e
Description
The application below crashes upon closing:
0 __GI_raise 56 0x7ffff6065bb9 1 __GI_abort 89 0x7ffff6068fc8 2 __libc_message 175 0x7ffff60a2e14 3 malloc_printerr 4996 0x7ffff60af0ee 4 _int_free 3840 0x7ffff60af0ee 5 Object::~Object main.cpp 5 0x403a96 6 (anonymous namespace)::QObjectDeleter::~QObjectDeleter qv4qobjectwrapper.cpp 1018 0x7ffff727c7ed 7 (anonymous namespace)::QObjectDeleter::~QObjectDeleter qv4qobjectwrapper.cpp 1021 0x7ffff727c83a 8 QV4::MemoryManager::sweep qv4mm.cpp 377 0x7ffff7204463 9 QV4::MemoryManager::~MemoryManager qv4mm.cpp 515 0x7ffff7204d4a 10 QV4::ExecutionEngine::~ExecutionEngine qv4engine.cpp 421 0x7ffff71ec562 11 QV8Engine::~QV8Engine qv8engine.cpp 116 0x7ffff736b748 12 QV8Engine::~QV8Engine qv8engine.cpp 117 0x7ffff736b7d4 13 QJSEngine::~QJSEngine qjsengine.cpp 203 0x7ffff716f2d8 14 main main.cpp 54 0x40240b
#include <QtWidgets> #include <QJSEngine> #include <QtQml> class Object : public QObject { Q_OBJECT public: Object() { } }; Q_DECLARE_METATYPE(const Object*) class ObjectProcessor : public QObject { Q_OBJECT public: ObjectProcessor() { } Q_INVOKABLE void process(const Object *object) { qDebug() << object; } }; #define BUG //#define QML_WORKAROUND //#define HEAP_WORKAROUND int main(int argc, char** argv) { QApplication app(argc, argv); QMainWindow window; window.resize(400, 400); window.show(); #ifdef BUG ObjectProcessor objectProcessor; Object object; #ifdef QML_WORKAROUND QQmlEngine::setObjectOwnership(&objectProcessor, QQmlEngine::CppOwnership); QQmlEngine::setObjectOwnership(&object, QQmlEngine::CppOwnership); #endif #endif #ifdef HEAP_WORKAROUND ObjectProcessor* objectProcessor = new ObjectProcessor; Object *object = new Object; #endif qRegisterMetaType<const Object*>(); QJSEngine jsEngine; QJSValue evaluationResult = jsEngine.evaluate("function stuff(object, objectProcessor) { objectProcessor.process(object); }"); if (evaluationResult.isError()) { qWarning() << evaluationResult.toString(); } QJSValueList args; #if defined(BUG) || defined(QML_WORKAROUND) args << jsEngine.newQObject(&object) << jsEngine.newQObject(&objectProcessor); #endif #ifdef HEAP_WORKAROUND args << jsEngine.newQObject(object) << jsEngine.newQObject(objectProcessor); #endif QJSValue callResult = jsEngine.globalObject().property("stuff").call(args); if (callResult.isError()) { qWarning() << callResult.toString(); } return app.exec(); } #include "main.moc"
This seems to be because the engine takes ownership of the objects (which were declared on the stack):
http://qt-project.org/doc/qt-5/qjsengine.html#newQObject
One workaround is to declare the objects on the heap (uncomment the HEAP_WORKAROUND defined and comment out the others), but even Qt's examples use the stack-based object approach, and they crash too on closing, with the same stack trace:
http://qt-project.org/doc/qt-5/qjsengine.html#qobject-integration
QTBUG-37160 seems to acknowledge this issue; it is possible to control ownership using QQmlEngine::setObjectOwnership(), but that is a bit backwards, since it derives from QJSEngine. To see this workaround, uncomment the QML_WORKAROUND define.
setObjectOwnership() should be available in QJSEngine.