QJSEngine cleanup/destructor
-
@SGaist Hi, thank you very much.
Currently, I'm using the below code to try and delete QJSEngine:
if (jsEngine) { jsEngine->collectGarbage(); jsEngine->deleteLater(); }
This crashes the app after it executes. I tried it in a way where I set the parent of the QJSEngine to the main window and do not call
deleteLater
(i.e I let the window clean it up), but it causes a similar crash. The crash itself is the app triggering a breakpointis_block_type_valid(header->_block_use)
This is what I could get out of VS:
ucrtbased.dll!000007fed011c2f1() Unknown ucrtbased.dll!000007fed011f8a5() Unknown > HMARL_Test_Engine.exe!operator delete(void * block) Line 21 C++ HMARL_Test_Engine.exe!operator delete(void * block, unsigned __int64 __formal) Line 16 C++ HMARL_Test_Engine.exe!JSInterface::`scalar deleting destructor'(unsigned int) C++ Qt5Qmld.dll!QV4::QObjectWrapper::destroyObject(bool lastCall) Line 1107 C++ Qt5Qmld.dll!QV4::MemoryManager::sweep(bool lastSweep, void(*)(const char *) classCountPtr) Line 977 C++ Qt5Qmld.dll!QV4::MemoryManager::~MemoryManager() Line 1225 C++ [External Code] Qt5Qmld.dll!QV4::ExecutionEngine::~ExecutionEngine() Line 653 C++ [External Code] Qt5Qmld.dll!QJSEngine::~QJSEngine() Line 379 C++ [External Code] Qt5Cored.dll!qDeleteInEventHandler(QObject * o) Line 4620 C++ Qt5Cored.dll!QObject::event(QEvent * e) Line 1241 C++ Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3752 C++ Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3109 C++ Qt5Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1061 C++ Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 1452 C++ Qt5Cored.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1800 C++ Qt5Cored.dll!QEventDispatcherWin32::sendPostedEvents() Line 1093 C++ qwindowsd.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++ Qt5Cored.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned __int64 wp, __int64 lp) Line 247 C++ [External Code] Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 640 C++ qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 74 C++ Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 139 C++ Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 225 C++ Qt5Cored.dll!QCoreApplication::exec() Line 1364 C++ Qt5Guid.dll!QGuiApplication::exec() Line 1780 C++ Qt5Widgetsd.dll!QApplication::exec() Line 2910 C++ HMARL_Test_Engine.exe!main(int argc, char * * argv) Line 10 C++ HMARL_Test_Engine.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 104 C++ [External Code]
Let me know if you need any additional info. Also, apologies if the formatting is suboptimal.
-
Did you already check the bug report system for something related ?
-
@SGaist Yeah, I looked around, nobody seems to have the same problem. Should I report it there?
Also, just to clarify: I should be able to create and destroy QJSEngine objects this way? So it's not like I'm trying to make the framework do something it's not supposed to?
-
Although I haven't used that class extensively, I am not aware of such a limitation. So go on and create a report. Please provide a minimal compilable example.
-
@SGaist While making the minimal compilable example, I managed to find the actual source of the problem. It wasn't the destructor at all, at least not directly, but instead me exposing my "interface" to JavaScript. Below is a small example:
QJSEngine* jsEngine = new QJSEngine(); // Add ourselves to the JS engine QJSValue interface = jsEngine->newQObject(interfacePtr); // Expose interface in the global namespace jsEngine->globalObject().setProperty("INTERFACE", interface); // Do stuff... delete jsEngine; // <-- error happens here
It seems that using
newQObject
causes trouble once I try destroying the QJSEngine, and the documentation references this as well:If the given object is deleted outside of the engine's control, any attempt to access the deleted QObject's members through the JavaScript wrapper object (either by script code or C++) will result in a script exception.
So I suspect I need to "clean up" this object before deleting the engine, otherwise (presumably) some ownership issues come up when the JS heap is cleaned up. Unfortunately, I have no idea how to fix this. I tried using
deleteProperty
on the global object, but that did not work. -
-
@yah_nosh said in QJSEngine cleanup/destructor:
Okay, found the solution. I needed to change the ownership using
QQmlEngine::setObjectOwnership
, and the JS engine stops trying to delete my objects. So technically there was no bug at all, but the source code and documentation sorely needs an update.You should consider improving the documentation and submit a patch for that so everybody can benefit from the outcome of your findings.
-
Anyone can contribute to the documentation, the code, etc. You have to follow the procedures and rules but it's not some walled garden.