Qt5 新信号到 lambda 连接内存泄漏

Qt5 new signal to lambda connections memory leak

本文关键字:lambda 连接 内存 泄漏 新信号 信号 Qt5      更新时间:2023-10-16

新的Qt5信号和插槽语法允许我们不仅将信号连接到插槽,还可以连接到普通的旧函数和函子/lambda。现在的问题是,lambda是带有()运算符的基本对象,当你将信号连接到它们时,它们会被复制到qt内部类的某个地方。而且,当您断开信号与该函子的连接时,它会保留在 qt 内部。我不明白,这是正常行为吗?或者也许有一种方法可以在断开连接后销毁这些功能对象?

下面是一个示例:

//example
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTimer* timer = new QTimer();
    QSharedPointer<QMetaObject::Connection> connection(new QMetaObject::Connection());
    //functor is created and gets copied inside qt internals, connection variable is captured
    //inside the functor
    *connection.data() = QObject::connect(timer, &QTimer::timeout, [=]
    {
        qDebug() << "disconnected";
        QObject::disconnect(*connection.data());
    });
    timer->start(10000);
    return a.exec();
}
//example
现在,

当我在插槽断开连接后查看连接变量的强引用计数时,它保持 2,这意味着函子对象本身仍然活着并且很好,尽管它现在对我来说没有用。我错过了什么吗?

这个例子被过度设计了(为什么要使用 QSharedPointer?为什么要按值捕获它?)。但实际上Qt正在泄漏函子对象。

关键是内部连接列表只是被标记为脏,并且在删除发件人或连接新信号之前不会清除(请参阅 cleanConnectionList 的用法)。

我推送了几个应该修复此行为的补丁:https://codereview.qt-project.org/#change,42976 和 42979