我正在测试一个共享库,其中包含内部对 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 时不会调用它。
但是,如果我执行两次测试(通过添加一个 test2 插槽,它是 test1 的拷贝),那么它会被调用一次。
我的理解是,当发出信号时,它会停止 spy 事件循环,然后永远不会调用 deleteLater
。
之后,第二个事件循环在 test2 中开始,它处理来自前一个 test1 的未决删除。
是否正确? 谢谢。
最佳答案
是的,你是对的。由于 QSignalSpy
和 Foo
存在于同一个线程中,因此信号 mySignal
不是通过事件循环传递的,而是通过直接连接传递的。因此,事件循环在 myslot
中发出信号后立即停止。然而,由于 myslot
被同一个事件循环调用,控制权仅在 myslot
返回时返回给它。因此,当事件循环可能执行 deleteLater
请求的清理时,它已经停止了。
如果你想测试 m_obj
是否被正确清理,你可以创建一个额外的 QSignalSpy
并将其连接到 QObject::destroyed
表示每个 QObject
在被销毁时都会发出信号。
但是,您需要将 m_obj
作为 Foo
的依赖项传递到构造函数中或通过 setter 而不是在 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");
}
关于c++ - QObject::deleteLater 在我的 Qt 测试中没有按预期调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52405841/