gpt4 book ai didi

c++ - 按值将 shared_ptr 传递给 lambda 会泄漏内存

转载 作者:可可西里 更新时间:2023-11-01 15:07:51 30 4
gpt4 key购买 nike

我有以下代码:

void MyClass::onOpenModalBtnClicked() {
uiManager->load(L"data/ui/testmodal.json");
std::shared_ptr<UIElement> modal = uiManager->getElementById("loginModal");

if(modal) {
modal->getElementById("closeButton")->onClicked = [modal]() {
modal->hide();
};
}
}

这工作正常,单击按钮时关闭模式,onClickedstd::function .

我的应用开头也有这个:

#if defined(DEBUG) | defined (_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

这会在应用程序终止时打印出内存泄漏。

使用上面的代码我得到了很多内存泄漏,如果我将代码更改为下面它们都消失了:

void MyClass::onOpenModalBtnClicked() {
uiManager->load(L"data/ui/testmodal.json");
std::shared_ptr<UIElement> modal = uiManager->getElementById("loginModal");

if(modal) {
modal->getElementById("closeButton")->onClicked = [this]() {
uiManager->getElementById("loginModal")->hide();
};
}
}

我假设传入 shared_ptr按值将引用计数增加 1,然后此引用永远不会超出范围或在报告内存泄漏后超出范围。所以我在使用 shared_ptr 之后尝试在 lambda 中调用 reset 但随后我得到了这个编译器错误:

Error 1 error C2662: 'void std::shared_ptr<_Ty>::reset(void) throw()' : cannot convert 'this' pointer from 'const std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty> &'

所以问题是我如何使用捕获的 modal而不是得到那些内存泄漏?

编辑:所以我通过添加 mutable 摆脱了编译错误到 lambda。

if(modal) {
modal->getElementById("closeButton")->onClicked = [modal]() mutable {
modal->hide();
modal.reset();
};
}

现在,如果我单击关闭按钮并关闭应用程序,则不会出现内存泄漏,因为重置会清除该引用。但是,如果从未点击过按钮,我仍然会遇到泄漏。

最佳答案

您已经创建了一个 shared_ptr 循环。

modal 在其引用计数达到 0 之前无法销毁。然后将 shared_ptr 的拷贝传递给 modal 到 labmda 函数中,从而增加其引用计数。然后,您将该 lambda 函数分配给 modal 的成员。

这意味着模态总是由它的回调函数引用。但是,在 modal 没有引用计数之前,它的回调函数不能被销毁。 Modal 最终卡在了 1 的引用计数上。

通常的解决方案是将裸指针或(最好)弱指针传递给 lambda

关于c++ - 按值将 shared_ptr 传递给 lambda 会泄漏内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18818260/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com