QtWebEngine内部对象typeid返回无效引用,该bug归属Qt/Chromium还是macOS?
QtWebEngine内部对象调用typeid返回无效引用的问题分析
当对QtWebEngine的内部对象(如QtWebEngineCore::RenderWidgetHostViewQtDelegateItem)使用typeid运算符时,会返回无效引用,甚至出现输出中typeid: nullptr的异常情况,调用typeInfo.name()会直接导致程序崩溃,这明显不符合C++标准中typeid的定义。
复现代码
#include <QTimer> #include <QGuiApplication> #include <QtWebEngineQuick/QtWebEngineQuick> #include <QtWebEngineCore/QtWebEngineCore> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi); QGuiApplication app(argc, argv); class EventFilter : public QObject{ public: using QObject::QObject; QSet<const QMetaObject*> visited; bool eventFilter(QObject* obj, QEvent*) override { const QMetaObject* mo = obj->metaObject(); if(!visited.contains(mo)){ visited.insert(mo); const std::type_info& typeInfo = typeid(*obj); // the following action may crash: // typeInfo.name(); // prove it by checking the reference for validity: const std::type_info* typeInfoPtr = &typeInfo; if(mo && typeInfoPtr) qWarning("metaobject: %s, typeid: %p (%s)", mo->className(), typeInfoPtr, typeInfoPtr->name()); else if(mo) qWarning("metaobject: %s, typeid: nullptr", mo->className()); else qWarning("metaobject: nullptr, typeid: nullptr"); } return false; } } eventFilter; app.installEventFilter(&eventFilter); QQmlApplicationEngine engine; QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.loadData(R"( import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtWebEngineApplicationWindow { visible: true width: 500 height: 400 WebEngineView { id: webView anchors.fill: parent url: http://www.qt.io } } )"); QTimer::singleShot(2000, &app, QCoreApplication::quit); return app.exec(); }
运行输出
metaobject: QtWebEngineCore::RenderWidgetHostViewQtDelegateItem, typeid: nullptr
问题根源分析
- 排除macOS系统层面问题:macOS的clang/libc实现的
typeid完全符合C标准,常规场景下不会返回无效引用或nullptr,因此系统层面的可能性极低。 - Chromium层面的潜在原因:QtWebEngine基于Chromium构建,Chromium的部分内部对象可能采用了特殊编译策略,比如在编译单元中禁用了RTTI(
-fno-rtti),导致typeid无法获取有效类型信息;另外,Chromium的某些对象可能通过自定义内存分配器创建,破坏了C++的类型识别机制。 - Qt封装层面的问题:QtWebEngine在封装Chromium对象时,可能存在对象生命周期管理异常,或者对部分内部对象隐藏了类型信息;也有可能Qt在编译这些模块时,针对特定对象关闭了RTTI支持,导致
typeid失效。
替代解决方案
Qt的元对象系统是跨平台且可靠的类型识别方案,完全可以替代typeid的需求:
// 用Qt元对象获取类型名称,避免typeid的问题 const char* className = obj->metaObject()->className();
内容的提问来源于stack exchange,提问作者BuvinJ
相关产品推荐
相关产品推荐

