c++ - 使用 VS2019 构建时使用 Qt5qml 导致应用程序崩溃
问题描述
我有一个用VS2013
Qt编译的应用程序5.9.6
,它工作正常。现在我想升级 Qt 版本5.15.2
并用 . 编译它VS2019
。构建成功,我可以运行应用程序,但它总是在Qt5Qml
模块处崩溃。
我调试了很长时间,但仍然不知道为什么。也许5.15.2
与 VS2019 不完全兼容?
2020 年 4 月 20 日更新:我有一门课叫ExpressionEvaluator
class ExpressionEvaluator
{
public:
ExpressionEvaluator();
virtual ~ExpressionEvaluator();
bool evaluate(const QString &expression, const QVariantMap &values);
protected:
class ExpressionEvaluatorPrivate *d_ptr;
Q_DECLARE_PRIVATE(ExpressionEvaluator);
int gcCounter;
};
这是和的ExpressionEvaluatorPrivate
定义ExpressionEvaluator
class ExpressionEvaluatorPrivate
{
public:
QJSEngine engine;
QMutex mutex;
};
ExpressionEvaluator::ExpressionEvaluator()
: d_ptr(new ExpressionEvaluatorPrivate()),
gcCounter(0)
{}
ExpressionEvaluator::~ExpressionEvaluator()
{
Q_D(ExpressionEvaluator);
d->engine.collectGarbage();
delete d_ptr;
}
bool ExpressionEvaluator::evaluate(const QString &expression, const QVariantMap &values)
{
Q_D(ExpressionEvaluator);
QMutexLocker locker(&d->mutex);
// CRASH HERE
for (auto it = values.begin(); it != values.end(); ++it) {
d->engine.globalObject().setProperty(it.key(), d->engine.toScriptValue(it.value())); // <---CRASH HERE
}
QJSValue qjsValue = d->engine.evaluate(expression);
bool ok = qjsValue.toBool();
if (++gcCounter >= GC_CALL_LIMIT) {
d->engine.collectGarbage();
gcCounter = 0;
}
for (auto it = values.begin(); it != values.end(); ++it) {
d->engine.globalObject().deleteProperty(it.key());
}
return ok;
}
解决方案
经过很长时间的调试,这种痛苦。我终于找到了解决方案。(但我不清楚它为什么起作用:))。我只想在这里发布我的答案,这样如果有人像我一样遇到这个问题,可以找到解决方案。
如您所见,我有一个名为 的函数ExpressionEvaluator::evaluate
,该函数将涉及多线程。Qt 一切正常,5.9.6
但是当我升级到 Qt 时5.15.2
,应用程序经常崩溃,堆栈跟踪指向周围QJsEngine
的行d->engine.globalObject()
对于我的研究,也许这是问题所在:
QJsEngine
有一个调用gc
垃圾收集的函数gc
将与拥有引擎的线程一起运行。- 每当另一个线程尝试访问
globalObject()
或任何函数(如evaluate()
)时QJsEngine
,如果gc
同时调用 and if => crash
是的,就像我之前说的,我并不真正理解这个问题,但是有了这个猜测,我能够创建一个解决方案并且它有效!
这是我的解决方案:
- 我创建了另一个线程(事件循环线程)
QJsEngine
并将住在那个线程中(它的所有功能也将在这个线程上执行) - 当另一个线程被调用
evaluate()
时,它将发出一个信号并且该信号连接到插槽(插槽将完成工作 - 当然,这个插槽仅在一个线程中执行) - 该解决方案确保:
gc
所有函数都将在同一个线程上执行。
P / s:对不起,如果我的解释很难理解,但这个问题有点具体,它坚持我的应用程序,所以这是我能做的最好的。但是总结一下:make sure all the function of QJsEngine is called in the same thread
推荐阅读
- angular - 重新加载/刷新指令以在 Angular7 中更新 html 中的视图
- html - 我的 scss 文件无法正确通过,您能说出原因吗?
- apache-camel - 为骆驼 json-validator 组件设置自定义错误消息
- python - DataFrame:列的累积总和,直到达到条件并在新列中返回总和
- spring - Spring security OAuth2 令牌自省
- python - 选择 Python 解释器在 VScode 中不起作用
- scala - Scala 中避免 if-else 阶梯的数据帧设计规则引擎
- javascript - 如何获取动态表数据?
- css - 计算字体大小时的 CSS 验证解析错误
- jenkins - 我如何在 jenkins 中修复这个 kubernetes 插件