Подтвердить что ты не робот

Новый сигнал Qt5 для утечки памяти лямбда-соединений

Новый синтаксис сигналов и слотов Qt5 позволяет нам подключать сигналы не только к слотам, но также к простым старым функциям и функторам /lambdas. Теперь проблема заключается в том, что лямбды являются важными объектами с оператором(), а когда вы подключаете к ним сигналы, они копируются где-то в 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, а это значит, что сам объект-функтор все еще жив и здоров, хотя теперь мне это бесполезно. Я что-то пропустил?

4b9b3361

Ответ 1

Пример перенастроен (зачем использовать QSharedPointer? зачем его фиксировать по значению?). Но действительно Qt утечка объекта-функтора.

Дело в том, что список внутренних подключений просто помечен как грязный и не очищается до тех пор, пока ни один из отправителей не будет удален, или не будет подключен новый сигнал (см. использование cleanConnectionLists).

Я нажал пару патчей, которые должны исправить это поведение: https://codereview.qt-project.org/#change,42976 и 42979