如何清理或销毁 QJSEngine?

Posted

技术标签:

【中文标题】如何清理或销毁 QJSEngine?【英文标题】:How to clean up or destroy QJSEngine? 【发布时间】:2019-04-11 15:30:55 【问题描述】:

我正在使用 Qt 5.12 构建一个应用程序,用户将在其中加载通过其 API 与应用程序交互的 JS 脚本。这些脚本被捆绑到“项目”中(即多个相互依赖的 JS 模块),并且在任何时候我都希望只将一个项目加载到 JS 引擎中,所以如果用户加载不同的项目,我想要前一个要清理的上下文。

根据文档,我假设如果我只是删除 QJSEngine 对象并创建一个新对象,这将允许我创建一个新的 JS 上下文。

QJSEngine* jsEngine = new QJSEngine();

// Load JS modules and run code...

jsEngine->collectGarbage();
delete jsEngine;

jsEngine = new QJSEngine();

// Load new JS modules...

当我尝试运行此代码时,我在delete jsEngine 处收到访问冲突异常。这真的很奇怪,因为文档本身就说明了

QJSEngine 销毁期间不会从持久 JS 堆中收集垃圾。如果您需要释放所有内存,请在销毁 QJSEngine 之前手动调用 collectGarbage。

这对我来说意味着我应该能够做到这一点。有人有想法么?提前致谢!

【问题讨论】:

我什至尝试使用deleteLater,或者将主窗口设置为我创建的每个 QJSEngine 的父窗口(因此在关闭应用程序时清理它们),但问题仍然存在。出于某种原因,当我拥有多个实例时,或者如果我尝试在应用关闭时以外的任何其他时间删除一个实例,我就会遇到某种内存访问错误。 【参考方案1】:

好吧,原来我是个傻瓜,忘记包含一个重要细节:我的应用程序还使用QJSEngine::newQObject 向 JS 引擎公开了我的“javascript 接口”对象,所以我几乎只是重新创建 @987654321 @。

解决方案完全相同:使用QQmlEngine::setObjectOwnership 可以解决问题。

【讨论】:

【参考方案2】:

确保周围没有任何剩余的 QJSValue。

或者,如果您只想清理状态。清除 QJSEngine::globalObject(),或者只是避免使用根 JS 状态,这样项目之间就不会泄漏。

【讨论】:

好的,我刚刚发现问题的根源是:我使用 newQObject 将我的“接口”类暴露给 JS 全局对象(我让对象在调用时给自己一个指针函数),当我尝试删除 QJSEngine 时,这会导致崩溃。但是现在我要在删除之前“清理它”吗?我尝试在全局对象上使用“deleteProperty”,但没有奏效。 好问题。我会假设您需要以某种方式停止引用它,然后激活垃圾收集。请注意,桥接对象也有不同的所有权模型(如果我没记错的话,可以控制 C++ 或 JS) 见上面的答案。事实证明有一个直接的解决方案,但得到它是相当不直观的。不过,感谢您的 cmets,他们确实帮助我找到了正确的答案。

以上是关于如何清理或销毁 QJSEngine?的主要内容,如果未能解决你的问题,请参考以下文章

reactreact组件销毁中清理异步操作和取消请求

如何销毁dropzone js?

如何在 ExtJS 4.1 中销毁商店?

在 onDestroy 中进行所有清理是不是安全?

React学习笔记-7-销毁阶段