删除 QObject 后 Qt 信号仍在触发

Qt signal still firing after QObject deleted

本文关键字:信号 QObject Qt 删除      更新时间:2023-10-16

我有一个使用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的信号再次发送,并试图调用不存在的对象Abar()。但这怎么可能呢?当然,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中。

希望对您有所帮助。