【问题标题】:Qt 5.6 alpha QtWebEngine. How work with QWebEngineUrlRequestJob?Qt 5.6 alpha QtWebEngine。如何使用 QWebEngineUrlRequestJob?
【发布时间】:2016-02-29 06:33:14
【问题描述】:

我继承自 QWebEngineUrlSchemeHandler。 重新定义方法 requestStarted(QWebEngineUrlRequestJob *request)

在我尝试调用 QWebEngineUrlRequestJob::reply 之后

例如

void CustomUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request)
{
    qDebug() << "CustomUrlSchemeHandler::requestStarted -->>> " << request->requestUrl();

    QMimeDatabase HelpViewer;
    QMimeType mt = HelpViewer.mimeTypeForUrl(request->requestUrl());
    const QString mimeType = mt.name();
    QByteArray arr = QString::fromStdString("<html><body>Hello world</body></html>").toUtf8();
    QBuffer *buffer = new QBuffer(&arr, this);
    buffer->open(QIODevice::ReadOnly);
    request->reply(mimeType.toLatin1(), buffer);

    return;
}

但是程序崩溃了。 查看日志:

    [1126/113403:FATAL:weak_ptr.cc(26)] Check failed: sequence_checker_.CalledOnValidSequencedThread(). WeakPtrs must be checked on the same sequenced thread.
Backtrace:
    base::debug::StackTrace::StackTrace [0x11A78691+33] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\debug\stack_trace_win.cc:205)
    logging::LogMessage::~LogMessage [0x119CB2AF+63] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\logging.cc:544)
    base::internal::WeakReference::Flag::IsValid [0x119FB75A+234] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\memory\weak_ptr.cc:28)
    base::internal::WeakReference::is_valid [0x119FB7B2+50] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\memory\weak_ptr.cc:43)
    base::WeakPtr<base::ObserverListBase<content::ServiceWorkerContextObserver> >::get [0x109EF57F+31] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\memory\weak_ptr.h:204)
    base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__thiscall content::DownloadResourceHandler::*)(void)>,base::internal::TypeList<base::WeakPtr<content::DownloadResourceHandler> const &> >::MakeItSo [0x107B8ADB+11] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\bind_internal.h:300)
    base::internal::Invoker<base::IndexSequence<0>,base::internal::BindState<base::internal::RunnableAdapter<void (__thiscall content::DownloadResourceHandler::*)(void)>,void __cdecl(content::DownloadResourceHandler *),base::internal::TypeList<base::WeakPtr<c [0x107BAD0A+58] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\bind_internal.h:346)
    base::Callback<net::URLRequestContext * __cdecl(void)>::Run [0x1096CACF+47] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\callback.h:396)
    base::debug::TaskAnnotator::RunTask [0x11A9580D+541] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\debug\task_annotator.cc:64)
    base::MessageLoop::RunTask [0x119DAAF8+456] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:475)
    base::MessageLoop::DeferOrRunPendingTask [0x119D9204+52] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:485)
    base::MessageLoop::DoWork [0x119D974D+221] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:594)
    base::MessagePumpForIO::DoRunLoop [0x11A980A2+50] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_pump_win.cc:524)
    base::MessagePumpWin::RunWithDispatcher [0x11A99B42+130] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_pump_win.cc:51)
    base::MessagePumpWin::Run [0x11A99AAC+28] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_pump_win.cc:58)
    base::MessageLoop::RunHandler [0x119DA907+247] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:438)
    base::RunLoop::Run [0x11A0A2E6+70] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\run_loop.cc:56)
    base::MessageLoop::Run [0x119DA7BD+237] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:288)
    base::Thread::Run [0x11A20AF6+22] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\threading\thread.cc:199)
    content::BrowserThreadImpl::IOThreadRun [0x10603B74+52] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\content\browser\browser_thread_impl.cc:212)
    content::BrowserThreadImpl::Run [0x1060498B+235] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\content\browser\browser_thread_impl.cc:246)
    base::Thread::ThreadMain [0x11A215F9+745] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\threading\thread.cc:248)
    base::`anonymous namespace'::ThreadFunc [0x11A283B6+262] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\threading\platform_thread_win.cc:84)
    BaseThreadInitThunk [0x75D57C04+36]
    RtlInitializeExceptionChain [0x77E4AD1F+143]
    RtlInitializeExceptionChain [0x77E4ACEA+90]
    (No symbol) [0x00000000]

【问题讨论】:

  • 据我所知,Qt 5.6 beta 还没有发布……你的意思是 alpha 吗?但是,由于您使用的是“BETA”,因此如果程序崩溃,您不应该感到惊讶。在bugreports.qt.io 创建错误报告
  • 我从提交 f128a9a7e1009d9ee11665dce08d5bfafa91ef66 构建 Qt;这是目前 5.6 的最新提交

标签: c++ qt qwebkit qt5.6


【解决方案1】:

崩溃的原因并不明显,因为Qt documentation 不清楚应该如何实现QWebEngineUrlSchemeHandler 的细节。

您的程序崩溃是因为QWebEngineUrlRequestJob::reply() 稍后使用了 buffer 参数,超出了调用者的范围,可能来自不同的线程。您在堆栈上声明的局部变量QByteArray arr(并用作缓冲区的后备存储)将超出范围,QWebEngine 将访问无效指针。

另一件事是,reply() 不获取传递的 buffer 对象的所有权并且从不删除它。这引入了内存泄漏。出于与上述相同的原因,您不能在调用reply() 后立即删除它。为确保 buffer 对象在不再需要时被删除,请将 requestdestroyed() 信号连接到 bufferdeleteLater()插槽。

这是一个完整的工作且无泄漏的示例:

void CustomUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request)
{
    QBuffer *buffer = new QBuffer;
    connect(request, SIGNAL(destroyed()), buffer, SLOT(deleteLater()));

    buffer->open(QIODevice::WriteOnly);
    buffer->write("<html><body>Hello world!</body></html>");
    buffer->close();

    request->reply("text/html", buffer);
}

注意:您根本不需要使用QByteArrayQBuffer 的默认构造函数分配自己的存储空间。

【讨论】:

    【解决方案2】:

    崩溃的一个原因是 arr 超出范围。
    你必须改变

    QByteArray arr = QString::fromStdString("<html><body>Hello world</body></html>").toUtf8();
    QBuffer *buffer = new QBuffer(&arr, this);
    

    QByteArray *pArr = new QByteArray(QString::fromStdString("<html><body>Hello world</body></html>").toUtf8());
    QBuffer *buffer = new QBuffer(pArr, this);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多