删除 QObject 后 Qt 信号仍在触发
Qt signal still firing after QObject deleted
我有一个使用Qt的C++程序,带有一个GUI QObject,它有一个链接到函数(bar()
)的ComboBox(我们称之为foo
)。这个QObject称为对象A
。
组合框在构造函数中链接:
connect(foo, SIGNAL(currentIndexChanged(int)), SLOT(bar(int)));
在bar(int)
中,这个函数在函数的末尾被调用:
inspector->update();
在检查器的update
功能中,会发生以下情况:
A
被删除(delete A;
,几乎 - 它是用new
创建的)。创建一个与
A
类型相同的新实例,我们称之为对象B
。
这是初始化的,运行正常片刻,然后一切都变得非常糟糕。
程序出现段错误,但只是由于 Qt 错误。GDB 没有多大帮助,但通过 Valgrind memcheck 运行程序会产生大量无效读取,如下所示:
==23410== Invalid read of size 8
==23410== at 0xFE92D7A: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.9.5)
==23410== by 0x79DDC94: QComboBox::currentIndexChanged(QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.9.5)
==23410== by 0x79DFB2D: ??? (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.9.5)
...
==23410== Address 0x3218ca68 is 8 bytes inside a block of size 48 free'd
==23410== at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23410== by 0xFE9119A: QObjectPrivate::deleteChildren() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.9.5)
==23410== by 0x7913D4B: QWidget::~QWidget() (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.9.5)
在我看来,这似乎是来自foo
的信号再次发送,并试图调用不存在的对象A
bar()
。但这怎么可能呢?当然,delete A
也应该阻止任何信号通过?另外,我只更改一次组合框的值 - 为什么要发送多个信号?
我尝试过阻止信号,也尝试重新排列,但没有成功。
这是整个相关的Valgrind memcheck日志。
这是Qt的错误吗?还是我做错了什么?非常感谢任何帮助,包括进一步调试的帮助。
尝试这样做:
-
首先向班级添加成员
QMetaObject::Connection foo_barConnect;
。 -
在构造函数中,将
connect
保存在foo_barConnect
:
foo_barConnect = connect(foo, SIGNAL(currentIndexChanged(int)), SLOT(bar(int)));
- 在
update()
函数中,在delete
之前添加:
// Check if `foo_barConnect` is valid (connected)
if(foo_barConnect){
// Disconnect foo_bar connection
disconnect(foo_barConnect);
}
- 如果您重新
new
对象并且需要连接,请不要忘记重新connect
并将连接存储在foo_barConnect
中。
希望对您有所帮助。
相关文章:
- QObject::连接无法将信号连接到*this*对象的插槽
- QObject::连接不起作用 - 使用函数语法找不到信号
- 在另一个线程上发出 QObject 信号的正确方法?
- 可以在 QObject::connect() C++中连接 QML 对象现有信号?
- 当通过引用传递 QObject 时,C++信号的参数在 QML 中显示为"未定义"
- 我可以交换QObject儿童保持信号和连接的插槽吗?
- 删除 QObject 后 Qt 信号仍在触发
- 替换 QObject 与信号和插槽一起使用时的异常
- .Qt :阻止 QObject 接收信号
- Qt-Qml连接到上下文属性的QObject属性的信号
- QObject::connect:未找到信号
- 将QObject接口信号连接到lambda插槽
- QObject::connect:没有这样的信号progressbarV::keyReleaseEvent()
- 在传递的对象即将被销毁之前,发出将QObject指针作为参数传递的信号是否安全
- 如何使用新的QObject::连接语法与函数指针将QSslSocket::错误信号连接到插槽
- QObject::connect:在 c++ Qt 5.3 中连接 qml 信号时没有这样的信号
- 在信号/插槽处理过程中删除QObject
- 找到“已销毁(QObject*)”信号的发送方
- QObject::connect:没有这样的信号mouseReleaseEvent
- 使用QObject::connect()时,类型签名是否重要,用于将函数连接到信号