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

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

20

Решение

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

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

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

8

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]