在Qt应用程序中诊断段错误时遇到问题
Trouble diagnosing segfault in Qt application
我有一个使用QtWebKit的应用程序。 它加载 URL 并导出渲染树上的一些统计信息。 这部分代码导致问题:
...
if (mPage != 0) {
disconnectSignals(mPage);
delete mPage;
}
mPage = new Page(); //subclass of QWebPage
connectSignals(mPage);
QNetworkRequest req;
req.setUrl("http://...");
mPage->mainFrame()->load(req, QNetworkAccessManager::GetOperation);
第一次运行上面的代码 mPage=0 时,页面加载正常,其他一切都按预期进行。 第二次,它是指向先前创建的页面的指针,因此它会断开连接并被删除。 在 load() 将控制权返回到主事件循环后,我得到了一个带有以下堆栈跟踪的 SIGSEGV。
#0 0x00007ffff49a1e56 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#1 0x00007ffff6842972 in QWebFrame::loadFinished(bool) () from /home/ubuntu/3rdparty/qt- 4.8.1/lib/libQtWebKit.so.4
#2 0x00007ffff6881955 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#3 0x00007ffff6bde3ab in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#4 0x00007ffff6c0ef14 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#5 0x00007ffff6e0183b in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#6 0x00007ffff6e016e8 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#7 0x00007ffff6e01755 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#8 0x00007ffff6e0218c in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#9 0x00007ffff49a20c1 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#10 0x00007ffff4d72b46 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtNetwork.so.4
#11 0x00007ffff4de91c5 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtNetwork.so.4
#12 0x00007ffff49a7286 in QObject::event(QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#13 0x00007ffff5243fa4 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtGui.so.4
#14 0x00007ffff5248e23 in QApplication::notify(QObject*, QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtGui.so.4
#15 0x00007ffff498e21c in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#16 0x00007ffff4991aba in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#17 0x00007ffff49bce53 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#18 0x00007ffff235ba5d in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#19 0x00007ffff235c258 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#20 0x00007ffff235c429 in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#21 0x00007ffff49bd27f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#22 0x00007ffff52e78ae in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtGui.so.4
#23 0x00007ffff498d002 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#24 0x00007ffff498d257 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from / home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#25 0x00007ffff4991db5 in QCoreApplication::exec() () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#26 0x0000000000408ba0 in main (argc=3, argv=<optimized out>) at RenderTreeAnalyzer.cpp:474
使用 deleteLater
计划删除mPage
,而不是直接删除它,因为事件队列中很可能有未传递的事件mPage
。
如果控制返回到事件循环,Qt会尝试访问已删除的对象,从而导致您的分段错误。
但是,从您的代码示例中,我并不完全理解为什么您需要newPage()
信号。
根据我的理解,mPage->deleteLater()
应该足够了(w.r.t. 避免赛段错误),并且您应该能够立即使用新值(即指向新Page
的指针)重新分配您的局部/成员变量mPage
。
如果您需要立即删除旧Page
,则需要返回到事件循环是正确的,因为它只会被删除。
您有几次机会触发事件循环并处理删除请求:
- 使用排队的信号/插槽设置
调用mPage->deleteLater()
后调用QApplication::processEvents();
以处理事件队列中的任何事件。- 调用
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
以仅处理所有延迟删除。 - 调用
QCoreApplication::sendPostedEvents(mPage, QEvent::DeferredDelete);
以仅处理mPage
的延迟删除。
免责声明:我没有明确尝试过这些建议(至少最近我记得没有),但我最近检查了很多Qt的事件管理源代码(当然,除了文档),所以我非常有信心它们都可以工作。
问题delete mPage;
. 我必须改用mPage->deleteLater(); emit getNext();
。 deleteLater() 计划在下次程序返回到主事件循环时删除对象。 emit getNext();
连接到一个插槽,该插槽在mPage = new Page();
时拾取。 它的连接类型是 Qt::QueuedConnection,因此它将在调用槽之前屈服于事件循环。 我不确定为什么,但您必须安排删除并像这样返回事件循环以正确关闭旧信号并设置新信号。
所以,这行得通,但如果有人能更详细地告诉我发生了什么,我会接受你的。 谢谢。
- 创建结构的数组时遇到分段错误
- 为什么我遇到分段错误?
- 这些是什么样的错误?即使我不在 Linux 上工作,我也遇到了 Linux 错误
- 为什么我在尝试模板时遇到视觉工作室C++错误
- 我在C++中遇到了这个奇怪的编译错误
- 我在 C++ 代码中遇到错误警告:控制到达非空函数 [-Wreturn 类型] 的末尾
- 我遇到了黑客排名中的问题"TWO STRINGS"的三个测试用例的分段错误。原因是什么?
- 我正在尝试一个傻瓜 C++ 练习,我遇到了一个错误,说类 'GraduateStudent' 没有任何名为 'advisor' 的字段
- 我在 ndk 中构建文件时遇到错误 android.mk
- 我在解决此错误时遇到问题.我正在努力在主函数中传递数组
- C++14 遇到奇怪的"use of deleted function"错误
- 在尝试使用递归查找集合子集的总数时,我遇到了分割错误
- 当我尝试在C++中对谷物进行序列化时,我遇到了一个奇怪的错误
- 我们在批处理模式下使用 G++ 时遇到错误
- 我不明白尝试使用字符串作为函数参数时遇到的错误
- 尝试通过多个函数移动数组,但遇到了我不知道如何修复的错误
- 我在c++中遇到了一个奇怪的错误,其中一个计算2个小整数加法的语句溢出到一个长值中
- 在visual Studio中构建代码时,我遇到错误,.h文件丢失
- 在Cython中使用C库时,我遇到了一个错误
- 错误:遇到非法内存访问