对象销毁后的事件
Events after Object destruction
我在慢速嵌入式系统中遇到了一个奇怪的问题:
如果我足够快,我可以通过双击按钮来使应用程序崩溃。
这背后的原因是,在此应用程序中,一旦有人单击"确定"按钮,窗口就会关闭。然后,窗口破坏发生在插槽中,该插槽与"pressed(("信号相关联(如果我使用"clicked(("信号,也会发生崩溃(。现在发生的情况是,第一个按钮按下正在关闭窗口,调用'deleteLater((。发生这种情况时,将捕获第二次按钮按下并将其放置在事件队列中。我后来从"已销毁"信号中收到一条消息,指出该窗口不再存在,但不久之后应用程序崩溃,因为 QT 的事件处理程序是由事件队列中的鼠标按下事件触发的。由于此事件,他尝试访问已删除的对象。
我已经尝试将"QCoreApplication::removePostedEvents(sender(((("放入由"destroy(("信号调用的插槽中,但这没有任何区别。
我使用的 QT 版本是 4.8.4。这也许在以后的版本中解决了吗?
以下是崩溃时的堆栈跟踪:
0 QMetaObject::addGuard qobject.cpp 400 0xd65390
1 QPointer<QAbstractButton>::QPointer qpointer.h 60 0x774948
2 QAbstractButtonPrivate::emitPressed qabstractbutton.cpp 561 0x771df8
3 QAbstractButton::mousePressEvent qabstractbutton.cpp 1098 0x773198
4 QToolButton::mousePressEvent qtoolbutton.cpp 709 0x804310
5 QWidget::event qwidget.cpp 8371 0x39cc90
6 QAbstractButton::event qabstractbutton.cpp 1082 0x7730cc
7 QToolButton::event qtoolbutton.cpp 1160 0x80594c
8 QApplicationPrivate::notify_helper qapplication.cpp 4562 0x347e88
9 QApplication::notify qapplication.cpp 4105 0x346144
10 QCoreApplication::notifyInternal qcoreapplication.cpp 946 0xd4df34
11 QCoreApplication::sendSpontaneousEvent qcoreapplication.h 234 0x34a9b8
12 QETWidget::translateMouseEvent qapplication_qws.cpp 3528 0x3cb73c
13 QApplication::qwsProcessEvent qapplication_qws.cpp 2974 0x3c9660
14 QEventDispatcherQWS::processEvents qeventdispatcher_qws.cpp 119 0x3d2468
15 QEventLoop::processEvents qeventloop.cpp 149 0xd4b4fc
16 QEventLoop::exec qeventloop.cpp 200 0xd4b690
17 QCoreApplication::exec qcoreapplication.cpp 1218 0xd4e6f0
18 QApplication::exec qapplication.cpp 3823 0x344fac
19 main main.cpp 650 0x21900c
这是程序中正在发生的事情的简化伪代码:
...
QWidget * m_pScreenW;
QSignalMapper * m_pMapper;
...
main()
{
....
connect( m_pUiState, SIGNAL( guiButtonPressed( const QString &, const QString & ) ),
m_pSetupController, SLOT( slotButtonActivated( const QString &, const QString & ) ) );
....
}
void raiseScreen(QObject* parent)
{
if ( m_pScreenW )
{
qDebug() << "~~~DeleteLater of screen: " << m_pScreenW;
m_pScreenW->deleteLater();
m_pScreenW = 0;
}
m_pScreenW = createNewScreenWithButtonsOnIt(parent);
}
QWidget* createNewScreenWithButtonsOnIt(QObject* parent)
{
....
m_pScreenW = new QWidget(parent);
m_pMapper = new QSignalMapper(m_pScreenW);
....
if(screenContainsButton()
{
QToolButton pTB = new QToolButton(m_pScreenW);
qDebug() << "~~+Creating toolbutton..." << pTB;
connect(pTB, SIGNAL(destroyed()), this, SLOT(slotButtonDestroyed()));
connect( p_pW, SIGNAL( pressed( ) ), m_pMapper, SLOT( map() ) );
}
...
connect( m_pMapper, SIGNAL( mapped( const QString & ) ),
this, SLOT( slotPreprocessGuiButton( const QString & ) ) );
connect( m_pWidget, SIGNAL(destroyed(QObject*)),
this, SLOT(slotWindowDestroyed(QObject*)));
....
}
void dngApp_c::slotWindowDestroyed(QObject* o)
{
qDebug() << "~~~Window destroyed:" << o;
}
void layout_n::manager_c::slotButtonDestroyed(void)
{
qDebug() << "~~~Toolbutton destroyed" << sender();
}
void dngApp_c::slotPreprocessGuiButton( const QString & p_strButton )
{
emit guiButtonPressed( strButton, "GUI" );
}
void ui_n::setupController_c::slotButtonActivated( const QString & p_strButtonId, const QString & p_strContext )
{
....
else if ( p_strButtonId == strButtonIdAbortImmediately )
{
//Do something time consuming here
....
QTimer::singleShot( 0, this, SLOT( slotOpenNewWindow() ) );
}
....
}
void ui_n::setupController_c::slotOpenNewWindow( void )
{
raiseScreen(0);
}
此外,还安装了一个事件过滤器来获取有关事件队列的其他信息:
appEventFilter_c::appEventFilter_c( dngApp_c * p_pApp ) :
QObject( p_pApp )
{
....
p_pApp->installEventFilter( this );
}
bool appEventFilter_c::eventFilter( QObject * p_pObject, QEvent * p_pEvent )
{
if ( p_pObject && p_pEvent )
{
switch ( p_pEvent->type() )
{
....
case QEvent::MouseButtonPress:
....
qDebug() << "---Pressed!!";
break;
case QEvent::MouseButtonRelease:
....
qDebug() << "---Released!!";
break;
default:
break;
}
}
}
如果我双击QToolButton,我会在命令行上得到以下输出,最后一行是我得到的最后一个输出:
Line 38: ~~+Creating toolbutton... layout_n::toolButton_c(0x2365250)
Line 39: ~~+Creating toolbutton... layout_n::toolButton_c(0x22bc008)
Line 40: ~~+Creating toolbutton... layout_n::toolButton_c(0x22b5290)
Line 41: ~~+Creating toolbutton... layout_n::toolButton_c(0x22bdf90)
Line 43: ~~+Creating toolbutton... layout_n::toolButton_c(0x2432880)
Line 44: ~~+Creating toolbutton... layout_n::toolButton_c(0x23796a0)
Line 47: ~~+Creating toolbutton... layout_n::toolButton_c(0x2554b10)
Line 48: ~~~Toolbutton destroyed QObject(0x22c91a0)
Line 49: ~~~Toolbutton destroyed QObject(0x2412420)
Line 50: ~~~Toolbutton destroyed QObject(0x24123c0)
Line 51: ~~~Toolbutton destroyed QObject(0x2414a20)
Line 52: ~~~Toolbutton destroyed QObject(0x241ff50)
Line 53: ~~~Toolbutton destroyed QObject(0x241ff70)
Line 54: ~~~Window destroyed: QObject(0x2354cf0, name = "6 34:03.188")
Line 55: ~~~Toolbutton destroyed QObject(0x2554b10)
Line 56: ~~~Window destroyed: QObject(0x2498580)
Line 62: ~~+Creating toolbutton... layout_n::toolButton_c(0x254c038)
Line 63: ~~+Creating toolbutton... layout_n::toolButton_c(0x254d010)
Line 64: ~~~Toolbutton destroyed QObject(0x254c038)
Line 72: ---Pressed!!
Line 94: ---Released!!
Line 95: --DeleteLater of screen: QWidget(0x235a2c0, name = "7 34:06.573")
Line 96: ~~+Creating toolbutton... layout_n::toolButton_c(0x25bdf90)
Line 97: ~~+Creating toolbutton... layout_n::toolButton_c(0x25bf7d0)
Line 98: ~~+Creating toolbutton... layout_n::toolButton_c(0x25c73d0)
Line 99: ~~+Creating toolbutton... layout_n::toolButton_c(0x25d1dc8)
Line 101: ~~+Creating toolbutton... layout_n::toolButton_c(0x25d72d0)
Line 106: ---Pressed!!
Line 107: ~~~Toolbutton destroyed QObject(0x2365250)
Line 108: ~~~Toolbutton destroyed QObject(0x22bc008)
Line 109: ~~~Toolbutton destroyed QObject(0x22b5290)
Line 110: ~~~Toolbutton destroyed QObject(0x22bdf90)
Line 111: ~~~Toolbutton destroyed QObject(0x2432880)
Line 112: ~~~Toolbutton destroyed QObject(0x23796a0)
Line 113: ~~~Toolbutton destroyed QObject(0x254d010)
Line 114: ~~~Window destroyed: QObject(0x231ec20)
Line 115: ~~~# Query: Trackdeletion PC Overlay
Line 116: ~~~Window destroyed: QObject(0x235a2c0, name = "7 34:06.573")
如果我现在向上移动堆栈跟踪,我会在级别 4 "QToolButton::mousePressEvent" 发现以下变量内容:
d @0x24b6020 QToolButtonPrivate
e @0xbea566ec QMouseEvent
opt QStyleOptionToolButton
this "" @0x254d010 QToolButton
但是具有此地址的工具箱按钮已经根据第 113 行被删除,这会导致程序崩溃。
为了进一步的信息,我现在附加一个回溯,当工具按钮被销毁时:
0 layout_n::manager_c::slotButtonDeleted layoutmanager.cpp 526 0x27eb70
1 layout_n::manager_c::qt_static_metacall moc_layoutmanager.cpp 243 0x28a4b4
2 QMetaObject::activate qobject.cpp 3540 0xd6c2f0
3 QObject::destroyed moc_qobject.cpp 149 0xd6dce8
4 QObject::~QObject qobject.cpp 843 0xd66c3c
5 QWidget::~QWidget qwidget.cpp 1705 0x38be4c
6 QAbstractButton::~QAbstractButton qabstractbutton.cpp 608 0x77284c
7 QToolButton::~QToolButton qtoolbutton.cpp 409 0x803c48
8 layout_n::toolButton_c::~toolButton_c layoutmanager.h 185 0x28b934
9 layout_n::toolButton_c::~toolButton_c layoutmanager.h 185 0x28b994
10 QObjectPrivate::deleteChildren qobject.cpp 1908 0xd68368
11 QWidget::~QWidget qwidget.cpp 1681 0x38bd90
12 QWidget::~QWidget qwidget.cpp 1705 0x38bec8
13 qDeleteInEventHandler qobject.cpp 4270 0xd6d858
14 QObject::event qobject.cpp 1175 0xd67384
15 QWidget::event qwidget.cpp 8846 0x39e564
16 QApplicationPrivate::notify_helper qapplication.cpp 4566 0x348428
17 QApplication::notify qapplication.cpp 4530 0x348260
18 QCoreApplication::notifyInternal qcoreapplication.cpp 947 0xd4e6b4
19 QCoreApplication::sendEvent qcoreapplication.h 231 0x34aee4
20 QCoreApplicationPrivate::sendPostedEvents qcoreapplication.cpp 1572 0xd4f950
21 QCoreApplication::sendPostedEvents qcoreapplication.cpp 1468 0xd4f548
22 QCoreApplication::sendPostedEvents qcoreapplication.h 236 0x3d2e68
23 QEventDispatcherQWS::flush qeventdispatcher_qws.cpp 164 0x3d2dbc
24 QCoreApplication::flush qcoreapplication.cpp 683 0xd4e0d0
25 QAbstractButton::mousePressEvent qabstractbutton.cpp 1101 0x773910
26 QToolButton::mousePressEvent qtoolbutton.cpp 710 0x804a90
27 QWidget::event qwidget.cpp 8371 0x39d230
28 QAbstractButton::event qabstractbutton.cpp 1085 0x77384c
29 QToolButton::event qtoolbutton.cpp 1162 0x8060cc
30 QApplicationPrivate::notify_helper qapplication.cpp 4566 0x348428
31 QApplication::notify qapplication.cpp 4108 0x3466e4
32 QCoreApplication::notifyInternal qcoreapplication.cpp 947 0xd4e6b4
33 QCoreApplication::sendSpontaneousEvent qcoreapplication.h 234 0x34af58
34 QETWidget::translateMouseEvent qapplication_qws.cpp 3539 0x3cbe08
35 QApplication::qwsProcessEvent qapplication_qws.cpp 2984 0x3c9d48
36 QEventDispatcherQWS::processEvents qeventdispatcher_qws.cpp 121 0x3d2b5c
37 QEventLoop::processEvents qeventloop.cpp 149 0xd4bc7c
38 QEventLoop::exec qeventloop.cpp 200 0xd4be10
39 QCoreApplication::exec qcoreapplication.cpp 1221 0xd4eec8
40 QApplication::exec qapplication.cpp 3823 0x34551c
41 main main.cpp 650 0x2192b4
在那里你可以看到,QWS 系统在第 34 行附近捕获了鼠标按钮按下,然后转发到相应的按钮,该按钮应该将按钮绘制为按下(第 25 行(并执行事件队列刷新以处理绘制事件,在这种情况下,它还会找到"稍后删除"(第 13 行(, 已由上一个鼠标按钮按下事件发布到事件队列并执行此删除。离开 flush 函数后,它将继续对非法指针变量进行操作,因为它自己的对象已经被销毁
了- 在事件过滤器之前发出对象的事件
- 对象销毁后的事件
- 如何在OpenGL中使用关键事件来转换对象
- 在另一个 QThread 上运行成员方法时,无法将事件发送到其他线程拥有的对象
- 是否可以在C++(17)中捕获某些对象属性的破坏性赋值事件
- 如何在主事件循环之前创建一些对象?
- QT:QT无法将事件发送到另一个线程拥有的对象 - 原因
- WXWIDGETS将鼠标事件连接到WXPAINTDC上的形状对象以删除
- 是否有任何可能的方法将事件(自定义)附加到在运行时创建的对象?[C 构建器]
- 将 ETW 文件对象与 DiskIO 事件相关联
- 是否有任何对象可以用作FIFO和弹出数据的事件
- C++使用 shared_ptr 安全地删除事件对象有效负载
- 将C 对象暴露于QML并收听更改事件
- 无法在另一个线程-QT中向对象发送已发布的事件
- Qt 事件过滤器未检测到对象名称
- Win32获取从窗口WNDProc发送事件的对象的HWND
- 如何设置并发::事件对象,仅当它现在未处于信号状态时
- 我可以在 QP(量子平台)活动对象中等待 Windows 事件(WaitForMultipleObjects)吗?
- 如何调试是否设置了 Windows 事件对象
- 不接受c++类的事件对象