QObject::d eleteLater在我的Qt测试中没有像预期的那样调用

QObject::deleteLater is not called as expected in my Qt Test

本文关键字:调用 eleteLater 我的 Qt QObject 测试      更新时间:2023-10-16

我正在测试一个共享库,其中包含对内部deleteLater的调用。 库中没有运行事件循环,因此应用程序的要求是运行事件循环,以便正确释放所有内存。

但在测试中,对象 dtor 未按预期调用。

例如:

void test1() 
{
Foo foo;
QSignalSpy spy(&foo, SIGNAL(mySignal(Status)));
foo.do(); // should trigger mySignal 
QVERIFY(spy.wait(10000)); // event loop started for 10 s max
QCOMPARE(spy.count(), 1);
QList<QVariant> sig = spy.takeFirst();
Foo::Status status = qvariant_cast<Foo::Status>(sig.at(0));
QVERIFY2(status == Foo:Ok, "Failed");
}

Foo如下所示:

class Foo : public QObject
{
Q_OBJECT
// ... methods, signals, slots..
private slots:
// this call is asynchronous (depends on a network reply)
void myslot() {
//..
m_obj->deleteLater();
emit mySignal(Foo:Ok);
}
};

我在 m_obj 的 dtor 中添加了一些调试打印,并且在执行 test1 时不会调用它。

但是,如果我执行测试两次(通过添加作为test1副本的test2插槽(,则调用一次。

我的理解是,当信号发出时,它会停止间谍事件循环,然后永远不会调用deleteLater。 之后,第二个事件循环在 test2 中启动,它处理上一个 test1 中的挂起删除。

正确吗? 谢谢。

是的,你是对的。由于QSignalSpyFoo位于同一线程中,因此信号mySignal不是通过事件循环传递,而是通过直接连接传递。因此,事件循环在发出信号后立即停止myslot。但是,由于myslot是由同一事件循环调用的,因此只有在myslot返回时,控制权才会返回给它。因此,当事件循环可能执行deleteLater请求的清理时,它已经停止了。

如果要测试是否正确清理m_obj,则可以创建一个附加QSignalSpy并将其连接到每个QObject在被销毁时发出的QObject::destroyed信号。

但是,您需要将m_obj作为依赖项传入,以在构造函数中或通过资源库Foo,而不是在Foo本身中构造它。

然后,测试可能如下所示:

void test1()
{
auto obj = new Obj{}; // will be assigned to `Foo::m_obj`
Foo foo{obj};
QSignalSpy deletion_spy(obj, &QObject::destroyed);
QSignalSpy mysignal_spy(&Foo, &Foo::mySignal);
QVERIFY(deletion_spy.wait(10000));
QCOMPARE(deletion_spy.count(), 1); // verify that `obj` got deleted
QCOMPARE(mysignal_spy.count(), 1);
QList<QVariant> sig = spy.takeFirst();
Foo::Status status = qvariant_cast<Foo::Status>(sig.at(0));
QVERIFY2(status == Foo:Ok, "Failed");
}