Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-41171

QJSEngine has no way of controlling object ownership

    XMLWordPrintable

Details

    • 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.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            mitch_curtis Mitch Curtis
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes