QProgressDialog :: setValue产生随机堆栈溢出

时间:2020-04-02 10:16:54

标签: c++ windows qt ubuntu stack-overflow

我正在开发一个无法共享源代码的大项目。在该项目中,我们在Windows中(而不是在ubuntu中)收到一些可重现的堆栈溢出错误,调试器的堆栈跟踪显示进度对话框设置为窗口模式,递归调用QProgressDialog :: setValue(int)。

我创建了QProgressDialog的这个小example,以尝试重现该错误。尽管在这个示例中(在Windows或Ubuntu中)我都没有遇到堆栈溢出错误,但是当我通过在调试器中添加断点来查看QProgressDailog :: setValue时,我看到它也以递归方式调用自己(在两个OS中) ,只是没有足够的时间来产生堆栈溢出。最令人印象深刻的是,有时它只调用一次QPrigressDialog :: setValue。

查看调用堆栈或窗口的示例:

Qt5Widgets.dll!QProgressDialog::setValue(int progress) Line 653 C++
[Inline Frame] Qt5Core.dll!QtPrivate::QSlotObjectBase::call(QObject *) Line 398 C++
Qt5Core.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 626    C++
Qt5Core.dll!QObject::event(QEvent * e) Line 1339    C++
Qt5Widgets.dll!QWidget::event(QEvent * event) Line 9094 C++
Qt5Widgets.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3687 C++
Qt5Widgets.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3639   C++
Qt5Core.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1075 C++
[Inline Frame] Qt5Core.dll!QCoreApplication::sendEvent(QObject *) Line 1470 C++
Qt5Core.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1815 C++
qwindows.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++
Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 525 C++
qwindows.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 75    C++
Qt5Widgets.dll!QProgressDialog::setValue(int progress) Line 663 C++
[Inline Frame] Qt5Core.dll!QtPrivate::QSlotObjectBase::call(QObject *) Line 398 C++
Qt5Core.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 626    C++
Qt5Core.dll!QObject::event(QEvent * e) Line 1339    C++
Qt5Widgets.dll!QWidget::event(QEvent * event) Line 9094 C++
Qt5Widgets.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3687 C++
Qt5Widgets.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3639   C++
Qt5Core.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1075 C++
[Inline Frame] Qt5Core.dll!QCoreApplication::sendEvent(QObject *) Line 1470 C++
Qt5Core.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1815 C++
qwindows.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++
Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 525 C++
qwindows.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 75    C++
Qt5Widgets.dll!QProgressDialog::setValue(int progress) Line 663 C++
[Inline Frame] Qt5Core.dll!QtPrivate::QSlotObjectBase::call(QObject *) Line 398 C++
Qt5Core.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 626    C++
Qt5Core.dll!QObject::event(QEvent * e) Line 1339    C++
Qt5Widgets.dll!QWidget::event(QEvent * event) Line 9094 C++
Qt5Widgets.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3687 C++
Qt5Widgets.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3639   C++
Qt5Core.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1075 C++
[Inline Frame] Qt5Core.dll!QCoreApplication::sendEvent(QObject *) Line 1470 C++
Qt5Core.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1815 C++
qwindows.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++
Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 525 C++
qwindows.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 75    C++
Qt5Widgets.dll!QProgressDialog::setValue(int progress) Line 663 C++
[Inline Frame] Qt5Core.dll!QtPrivate::QSlotObjectBase::call(QObject *) Line 398 C++
Qt5Core.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 626    C++
Qt5Core.dll!QObject::event(QEvent * e) Line 1339    C++
Qt5Widgets.dll!QWidget::event(QEvent * event) Line 9094 C++
Qt5Widgets.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3687 C++
Qt5Widgets.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3639   C++
Qt5Core.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1075 C++
[Inline Frame] Qt5Core.dll!QCoreApplication::sendEvent(QObject *) Line 1470 C++
Qt5Core.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1815 C++
qwindows.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++
Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 525 C++
qwindows.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 75    C++
Qt5Widgets.dll!QProgressDialog::setValue(int progress) Line 663 C++
[Inline Frame] Qt5Core.dll!QtPrivate::QSlotObjectBase::call(QObject *) Line 398 C++
Qt5Core.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 626    C++
Qt5Core.dll!QObject::event(QEvent * e) Line 1339    C++
Qt5Widgets.dll!QWidget::event(QEvent * event) Line 9094 C++
Qt5Widgets.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3687 C++
Qt5Widgets.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3639   C++
Qt5Core.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1075 C++
[Inline Frame] Qt5Core.dll!QCoreApplication::sendEvent(QObject *) Line 1470 C++
Qt5Core.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1815 C++
qwindows.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++
Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 525 C++
qwindows.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 75    C++
Qt5Widgets.dll!QProgressDialog::setValue(int progress) Line 663 C++
[Inline Frame] Qt5Core.dll!QtPrivate::QSlotObjectBase::call(QObject *) Line 398 C++
Qt5Core.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 626    C++
Qt5Core.dll!QObject::event(QEvent * e) Line 1339    C++
Qt5Widgets.dll!QWidget::event(QEvent * event) Line 9094 C++
Qt5Widgets.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3687 C++
Qt5Widgets.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3639   C++
Qt5Core.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1075 C++
[Inline Frame] Qt5Core.dll!QCoreApplication::sendEvent(QObject *) Line 1470 C++
Qt5Core.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1815 C++
qwindows.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++
Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 525 C++
qwindows.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 75    C++
Qt5Widgets.dll!QProgressDialog::setValue(int progress) Line 663 C++
[Inline Frame] Qt5Core.dll!QtPrivate::QSlotObjectBase::call(QObject *) Line 398 C++
Qt5Core.dll!QMetaCallEvent::placeMetaCall(QObject * object) Line 626    C++
Qt5Core.dll!QObject::event(QEvent * e) Line 1339    C++
Qt5Widgets.dll!QWidget::event(QEvent * event) Line 9094 C++
Qt5Widgets.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3687 C++
Qt5Widgets.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3639   C++
Qt5Core.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1075 C++
[Inline Frame] Qt5Core.dll!QCoreApplication::sendEvent(QObject *) Line 1470 C++
Qt5Core.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data) Line 1815 C++
qwindows.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82 C++
Qt5Core.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 525 C++
qwindows.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 75    C++
[Inline Frame] Qt5Core.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag>) Line 138   C++
Qt5Core.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 225 C++
Qt5Core.dll!QCoreApplication::exec() Line 1383  C++
progress_bar.exe!main(int argc, char * * argv) Line 9   C++
[External Code] 

查看ubuntu上调用堆栈的示例:

#0  0x00007ffff76fa330 in QProgressDialog::setValue(int) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#1  0x00007ffff60a3dec in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<int>, void, void (QProgressDialog::*)(int)>::call(void (QProgressDialog::*)(int), QProgressDialog*, void**) ()
    at /home/apalomer/programming_workspace/progress_bar_example/build/libthreadedworker.so
#2  0x00007ffff60a3ba4 in void QtPrivate::FunctionPointer<void (QProgressDialog::*)(int)>::call<QtPrivate::List<int>, void>(void (QProgressDialog::*)(int), QProgressDialog*, void**) ()
    at /home/apalomer/programming_workspace/progress_bar_example/build/libthreadedworker.so
#3  0x00007ffff60a3759 in QtPrivate::QSlotObject<void (QProgressDialog::*)(int), QtPrivate::List<int>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) ()
    at /home/apalomer/programming_workspace/progress_bar_example/build/libthreadedworker.so
#4  0x00007ffff6ef30c2 in QObject::event(QEvent*) (this=0x555555b74610, e=<optimized out>) at kernel/qobject.cpp:1247
#5  0x00007ffff751775b in QWidget::event(QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#6  0x00007ffff74d883c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#7  0x00007ffff74e0104 in QApplication::notify(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#8  0x00007ffff6ec38d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x555555b74610, event=event@entry=0x7fffc80037a0) at kernel/qcoreapplication.cpp:1024
#9  0x00007ffff6ec604d in QCoreApplication::sendEvent(QObject*, QEvent*) (event=0x7fffc80037a0, receiver=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:233
#10 0x00007ffff6ec604d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (receiver=receiver@entry=0x0, event_type=event_type@entry=0, data=0x55555576fef0)
    at kernel/qcoreapplication.cpp:1699
#11 0x00007ffff6ec65d8 in QCoreApplication::sendPostedEvents(QObject*, int) (receiver=receiver@entry=0x0, event_type=event_type@entry=0) at kernel/qcoreapplication.cpp:1553
#12 0x00007ffff6f1d263 in postEventSourceDispatch(GSource*, GSourceFunc, gpointer) (s=0x5555558952a0) at kernel/qeventdispatcher_glib.cpp:276
#13 0x00007ffff4221417 in g_main_context_dispatch () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#14 0x00007ffff4221650 in  () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#15 0x00007ffff42216dc in g_main_context_iteration () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#16 0x00007ffff6f1c88f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x5555558d2b80, flags=...) at kernel/qeventdispatcher_glib.cpp:423
#17 0x00007ffff76fa4c7 in QProgressDialog::setValue(int) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#18 0x00007ffff60a3dec in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<int>, void, void (QProgressDialog::*)(int)>::call(void (QProgressDialog::*)(int), QProgressDialog*, void**) ()
    at /home/apalomer/programming_workspace/progress_bar_example/build/libthreadedworker.so
#19 0x00007ffff60a3ba4 in void QtPrivate::FunctionPointer<void (QProgressDialog::*)(int)>::call<QtPrivate::List<int>, void>(void (QProgressDialog::*)(int), QProgressDialog*, void**) ()
    at /home/apalomer/programming_workspace/progress_bar_example/build/libthreadedworker.so
#20 0x00007ffff60a3759 in QtPrivate::QSlotObject<void (QProgressDialog::*)(int), QtPrivate::List<int>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) ()
    at /home/apalomer/programming_workspace/progress_bar_example/build/libthreadedworker.so
#21 0x00007ffff6ef30c2 in QObject::event(QEvent*) (this=0x555555b74610, e=<optimized out>) at kernel/qobject.cpp:1247
#22 0x00007ffff751775b in QWidget::event(QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#23 0x00007ffff74d883c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#24 0x00007ffff74e0104 in QApplication::notify(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#25 0x00007ffff6ec38d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x555555b74610, event=event@entry=0x7fffc8002ef0) at kernel/qcoreapplication.cpp:1024
#26 0x00007ffff6ec604d in QCoreApplication::sendEvent(QObject*, QEvent*) (event=0x7fffc8002ef0, receiver=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:233
#27 0x00007ffff6ec604d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (receiver=receiver@entry=0x0, event_type=event_type@entry=0, data=0x55555576fef0)
    at kernel/qcoreapplication.cpp:1699
#28 0x00007ffff6ec65d8 in QCoreApplication::sendPostedEvents(QObject*, int) (receiver=receiver@entry=0x0, event_type=event_type@entry=0) at kernel/qcoreapplication.cpp:1553
#29 0x00007ffff6f1d263 in postEventSourceDispatch(GSource*, GSourceFunc, gpointer) (s=0x5555558952a0) at kernel/qeventdispatcher_glib.cpp:276
#30 0x00007ffff4221417 in g_main_context_dispatch () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#31 0x00007ffff4221650 in  () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#32 0x00007ffff42216dc in g_main_context_iteration () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#33 0x00007ffff6f1c88f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x5555558d2b80, flags=...) at kernel/qeventdispatcher_glib.cpp:423
#34 0x00007ffff6ec190a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fffffffcfb0, flags=..., flags@entry=...) at kernel/qeventloop.cpp:212
#35 0x00007ffff6eca9b4 in QCoreApplication::exec() () at kernel/qcoreapplication.cpp:1297
#36 0x0000555555554cb4 in main ()

关于如何解决此递归的任何想法?我应该将其移至错误报告吗?特别是如果我手动执行该程序。

我已经在Windows 10,Visual Studio 16.5.2,MSVC 19.25.28612.0和Qt 5.14.2以及Qt 5.14.1,Qt 5.9.5中对此进行了测试。另外,我已经在Ubuntu 18.04,g ++ 7.5.0和Qt 5.9.5中进行了尝试。

1 个答案:

答案 0 :(得分:1)

从您的示例代码中可以得出的结论:

  1. 每200毫秒就有一个工作线程将事件发布到主事件队列中。 (由于从工作线程发出的信号处于排队连接中,这将在接收者的线程事件循环中发布事件)
  2. QProgressDialog源代码清楚地表明,在模式模式下进行配置时,它会在其setValue方法中调用QCoreApplication :: processEvents。

因此,为引起堆栈溢出,在对话框开始处理它们之前,一个线程应该能够在对话框的线程事件循环中发布足够的事件。

一旦它将开始处理此事件链,它将自行递归并可能导致堆栈溢出。如果您使用调试器进入主线程,则可以解释为什么另一个线程能够在主偶数循环中累积如此多的事件。

我不知道这可能是Qt项目的一个错误,但是您仍然可以在其IRC频道上提问或打开一个问题,然后查看它的出处。

尽管如此,一种可能的即席解决方案是避免来自工作线程的信号突发,以免落入这种陷阱(例如,每秒触发一次状态更新,而不是在最终用户短的固定时间内)。