C++ Qt5至lambda连接的新信号内存泄漏
新的Qt5信号和插槽语法使我们不仅可以将信号连接到插槽,还可以连接到普通的旧函数和functor/lambda。现在的问题是,lambda本质上是带有()运算符的对象,当您将信号连接到它们时,它们会被复制到qt内部类的某个地方。而且,当你从那个函子上断开信号时,它保持在qt内部。我不明白,这是正常的行为吗?或者有没有办法在断开连接后销毁这些功能对象 下面是一个例子:C++ Qt5至lambda连接的新信号内存泄漏,c++,c++11,signals,qt5,slot,C++,C++11,Signals,Qt5,Slot,新的Qt5信号和插槽语法使我们不仅可以将信号连接到插槽,还可以连接到普通的旧函数和functor/lambda。现在的问题是,lambda本质上是带有()运算符的对象,当您将信号连接到它们时,它们会被复制到qt内部类的某个地方。而且,当你从那个函子上断开信号时,它保持在qt内部。我不明白,这是正常的行为吗?或者有没有办法在断开连接后销毁这些功能对象 下面是一个例子: //example int main(int argc, char *argv[]) { QApplication a(
//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
//示例
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
QTimer*定时器=新的QTimer();
QSharedPointer连接(新的QMetaObject::connection());
//functor被创建并复制到qt内部,连接变量被捕获
//函子内部
*connection.data()=QObject::connect(计时器和QTimer::超时,[=]
{
qDebug()开始(10000);
返回a.exec();
}
//范例
现在,当我在插槽断开连接后查看连接变量的强引用计数时,它保持为2,这意味着函子对象本身仍然是活动的,尽管它现在对我没有任何用处。我是否遗漏了什么?该示例设计过度(为什么要使用QSharedPointer?为什么要通过值捕获它?).但实际上Qt正在泄漏函子对象 关键是,内部连接列表只是标记为脏的,并且在删除发送方或连接新信号之前不会清除(请参阅的用法)
我推了几个补丁来修复这个行为:和42979当你破坏计时器时会发生什么?我也这么想过,但是引用计数仍然保持为2=/如果我不将连接变量存储在该'*connection.data()中,它将变为1的唯一方式='分离并删除计时器。这仍然很奇怪。我已经有一段时间没有使用Qt了,但是你不能使用返回的
QMetaObject::Connection
,使用相同的参数重新连接吗?这可以解释为什么它保留对函数的引用。我认为没有重新连接的方法。从源代码中,disconnect()将接收器设置为0。因此无法恢复连接。我认为OP确实发现了内存泄漏。请提交错误报告。是的,我知道它可能有点设计过度,但我需要共享指针,以便能够轻松监视对它的引用数,查看functor对象是否仍然存在,我确实有一个类似的逻辑不在主函数中的项目,所以我不能在那里通过引用捕获连接。