QWebEngineView 在 load() 或 page() 方法上崩溃
QWebEngineView crashes on load() or page() method
我正在努力将 Qt 5.5、QWebView 项目移植到 Qt 5.6(测试版)、QWebEngine。我已经阅读了移植指南 here。我的代码如下所示:
.h 文件定义 _view 如下:
QWebEngineView* _view;
.cpp 构造函数(class 继承自 QWidget)具有:
QVBoxLayout* vbox = new QVBoxLayout(this);
_view = new QWebEngineView(this);
connect(_view, SIGNAL(loadFinished(bool)), this, SLOT(loadPageFinished(bool)));
QString webDir = getReportBasePath() + no_tr("/index.html#") + startingPage;
// QWebEnginePage *page = _view->page(); // <-- CRASH!!
_view->load( QUrl("file:///" + webDir ) ); // <-- CRASH!!
_view->show();
vbox->addWidget(_view);
在执行 page() 或 load() 方法后,整个过程崩溃了:
Unhandled exception at 0x67019C66 (Qt5Cored.dll) in qxs.exe: 0xC0000005:
Access violation reading location 0x00000000.
我已验证 _view 指针不为空。
如果您查看文档,他们有一个示例 here 几乎与我上面的代码相同。我还尝试将 load() 调用替换为与他们的相同:
view->load(QUrl("http://qt-project.org/"));
它仍然崩溃。知道是什么导致了这些崩溃吗?
我需要先创建一个QWebEnginePage然后在QWebEngineView上setPage()吗? (我假设不是...)它是否与我正在使用的 Qt 二进制文件(为 Windows 32 位 MSVC 2013 预构建)有关?
堆栈跟踪的相关部分:
Qt5WebEngineWidgetsd.dll!QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile * _profile) Line 95 C++
Qt5WebEngineWidgetsd.dll!QWebEnginePage::QWebEnginePage(QObject * parent) Line 393 C++
Qt5WebEngineWidgetsd.dll!QWebEngineView::page() Line 145 C++
Qt5WebEngineWidgetsd.dll!QWebEngineView::load(const QUrl & url) Line 157 C++
qxs.exe!ReportWidget::ReportWidget(QcaMain * qm, QWidget * parent, QString startingPage) Line 321 C++
这里崩溃了:
QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
: adapter(new WebContentsAdapter)
, history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this)))
, profile(_profile ? _profile : QWebEngineProfile::defaultProfile())
, settings(new QWebEngineSettings(profile->settings()))
, view(0)
, isLoading(false)
, scriptCollection(new QWebEngineScriptCollectionPrivate(browserContextAdapter()->userScriptController(), adapter.data()))
, m_backgroundColor(Qt::white)
, fullscreenMode(false)
{
memset(actions, 0, sizeof(actions));
}
我认为这可能与 _profile 为 NULL 有关,所以我尝试首先设置一个 QWebEngineProfile,如下所示:
QWebEnginePage* page = new QWebEnginePage( QWebEngineProfile::defaultProfile(), _view );
_view->setPage( page );
然后它在 qwebengineprofile.cpp 这里崩溃了:
static QWebEngineProfile* profile = new QWebEngineProfile(
new QWebEngineProfilePrivate(BrowserContextAdapter::defaultContext()),
BrowserContextAdapter::globalQObjectRoot());
具有堆栈跟踪:
Qt5Cored.dll!convert_to_wchar_t_elided(wchar_t * d, unsigned int space, const char * s) Line 256 C++
Qt5Cored.dll!qt_message_fatal(QtMsgType __formal, const QMessageLogContext & context, const QString & message) Line 1593 C++
Qt5Cored.dll!QMessageLogger::fatal(const char * msg, ...) Line 784 C++
Qt5WebEngineCored.dll!`anonymous namespace'::subProcessPath(void) C++
Qt5WebEngineCored.dll!WebEngineLibraryInfo::getPath(int) C++
Qt5WebEngineCored.dll!WebEngineContext::WebEngineContext(void) C++
Qt5WebEngineCored.dll!WebEngineContext::current(void) C++
Qt5WebEngineCored.dll!QtWebEngineCore::BrowserContextAdapter::defaultContext(void) C++
> Qt5WebEngineWidgetsd.dll!QWebEngineProfile::defaultProfile() Line 516 C++
问题已解决。我缺少 QWebEngine 所需的一些关键文件,否则它会崩溃。这些文件必须与可执行文件位于同一目录中。它们由 windeployqt.exe 工具放置在那里,因此这是确保您的 Qt 应用程序拥有 运行 所需的一切而不会崩溃的最佳方式。
qtwebengine_resources.pak
qtwebengine_resources_100p
qtwebengine_resources_200p.pak.pak
QtWebEngineProcess.exe
icudtl.dat
我的原因是我们的开发组以前使用 Qt 4.8,并使用内部方法将所需的 Qt dll 和诸如此类的东西复制到目标目录中。升级到 Qt 5.x 并添加 QWebEngine 时,我们没有意识到需要上述文件。
您可以设置 Windows 名为 QTWEBENGINEPROCESS_PATH
的环境变量
示例:
QTWEBENGINEPROCESS_PATH C:\Qt\Qt5.6.0.6\msvc2013_64\bin\QtWebEngineProcess.exe
使用此解决方案,无需将资源文件复制到项目输出文件夹中
我正在努力将 Qt 5.5、QWebView 项目移植到 Qt 5.6(测试版)、QWebEngine。我已经阅读了移植指南 here。我的代码如下所示:
.h 文件定义 _view 如下:
QWebEngineView* _view;
.cpp 构造函数(class 继承自 QWidget)具有:
QVBoxLayout* vbox = new QVBoxLayout(this);
_view = new QWebEngineView(this);
connect(_view, SIGNAL(loadFinished(bool)), this, SLOT(loadPageFinished(bool)));
QString webDir = getReportBasePath() + no_tr("/index.html#") + startingPage;
// QWebEnginePage *page = _view->page(); // <-- CRASH!!
_view->load( QUrl("file:///" + webDir ) ); // <-- CRASH!!
_view->show();
vbox->addWidget(_view);
在执行 page() 或 load() 方法后,整个过程崩溃了:
Unhandled exception at 0x67019C66 (Qt5Cored.dll) in qxs.exe: 0xC0000005:
Access violation reading location 0x00000000.
我已验证 _view 指针不为空。
如果您查看文档,他们有一个示例 here 几乎与我上面的代码相同。我还尝试将 load() 调用替换为与他们的相同:
view->load(QUrl("http://qt-project.org/"));
它仍然崩溃。知道是什么导致了这些崩溃吗?
我需要先创建一个QWebEnginePage然后在QWebEngineView上setPage()吗? (我假设不是...)它是否与我正在使用的 Qt 二进制文件(为 Windows 32 位 MSVC 2013 预构建)有关?
堆栈跟踪的相关部分:
Qt5WebEngineWidgetsd.dll!QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile * _profile) Line 95 C++
Qt5WebEngineWidgetsd.dll!QWebEnginePage::QWebEnginePage(QObject * parent) Line 393 C++
Qt5WebEngineWidgetsd.dll!QWebEngineView::page() Line 145 C++
Qt5WebEngineWidgetsd.dll!QWebEngineView::load(const QUrl & url) Line 157 C++
qxs.exe!ReportWidget::ReportWidget(QcaMain * qm, QWidget * parent, QString startingPage) Line 321 C++
这里崩溃了:
QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
: adapter(new WebContentsAdapter)
, history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this)))
, profile(_profile ? _profile : QWebEngineProfile::defaultProfile())
, settings(new QWebEngineSettings(profile->settings()))
, view(0)
, isLoading(false)
, scriptCollection(new QWebEngineScriptCollectionPrivate(browserContextAdapter()->userScriptController(), adapter.data()))
, m_backgroundColor(Qt::white)
, fullscreenMode(false)
{
memset(actions, 0, sizeof(actions));
}
我认为这可能与 _profile 为 NULL 有关,所以我尝试首先设置一个 QWebEngineProfile,如下所示:
QWebEnginePage* page = new QWebEnginePage( QWebEngineProfile::defaultProfile(), _view );
_view->setPage( page );
然后它在 qwebengineprofile.cpp 这里崩溃了:
static QWebEngineProfile* profile = new QWebEngineProfile(
new QWebEngineProfilePrivate(BrowserContextAdapter::defaultContext()),
BrowserContextAdapter::globalQObjectRoot());
具有堆栈跟踪:
Qt5Cored.dll!convert_to_wchar_t_elided(wchar_t * d, unsigned int space, const char * s) Line 256 C++
Qt5Cored.dll!qt_message_fatal(QtMsgType __formal, const QMessageLogContext & context, const QString & message) Line 1593 C++
Qt5Cored.dll!QMessageLogger::fatal(const char * msg, ...) Line 784 C++
Qt5WebEngineCored.dll!`anonymous namespace'::subProcessPath(void) C++
Qt5WebEngineCored.dll!WebEngineLibraryInfo::getPath(int) C++
Qt5WebEngineCored.dll!WebEngineContext::WebEngineContext(void) C++
Qt5WebEngineCored.dll!WebEngineContext::current(void) C++
Qt5WebEngineCored.dll!QtWebEngineCore::BrowserContextAdapter::defaultContext(void) C++
> Qt5WebEngineWidgetsd.dll!QWebEngineProfile::defaultProfile() Line 516 C++
问题已解决。我缺少 QWebEngine 所需的一些关键文件,否则它会崩溃。这些文件必须与可执行文件位于同一目录中。它们由 windeployqt.exe 工具放置在那里,因此这是确保您的 Qt 应用程序拥有 运行 所需的一切而不会崩溃的最佳方式。
qtwebengine_resources.pak
qtwebengine_resources_100p
qtwebengine_resources_200p.pak.pak
QtWebEngineProcess.exe
icudtl.dat
我的原因是我们的开发组以前使用 Qt 4.8,并使用内部方法将所需的 Qt dll 和诸如此类的东西复制到目标目录中。升级到 Qt 5.x 并添加 QWebEngine 时,我们没有意识到需要上述文件。
您可以设置 Windows 名为 QTWEBENGINEPROCESS_PATH
的环境变量
示例:
QTWEBENGINEPROCESS_PATH C:\Qt\Qt5.6.0.6\msvc2013_64\bin\QtWebEngineProcess.exe
使用此解决方案,无需将资源文件复制到项目输出文件夹中