gpt4 book ai didi

c++ - 这个 std::vector 和 std::shared_ptr 内存泄漏是一个错误吗?

转载 作者:太空宇宙 更新时间:2023-11-03 10:38:13 26 4
gpt4 key购买 nike

假设这个类Foo :

struct Foo {
std::shared_ptr<int> data;
std::shared_ptr<std::vector<Foo>> foos;
};
  • 它有一个指向 int 的指针

  • 它有一个指向将存在于该程序中的所有实例的指针(因此这些实例之一 == *this )

让我们创建一个 Foo 的实例看看 use_count()它的 .data将一些实例添加到 .foos 后的成员变量:

int main() {
Foo foo;
foo.data = std::make_shared<int>(5);
foo.foos = std::make_shared<std::vector<Foo>>();
foo.foos->resize(8);

for (auto & f : *foo.foos) {
f.data = foo.data;
f.foos = foo.foos;
}
std::cout << "use count: " << foo.data.use_count() << '\n';
}

输出:

use count: 9

这很好 (1 foo + 8 .foos )。然而,似乎当main()返回,仍然会有 9 8个指针指向.data !这可以通过放置 foo 来证明。进入本地范围并让一个额外的指针指向 .data观察这个指针 use_count()之后:

int main() {
std::shared_ptr<int> ptr;
std::cout << "use count | before: " << ptr.use_count() << '\n';

{ //begin scope
Foo foo;
foo.data = std::make_shared<int>(5);
foo.foos = std::make_shared<std::vector<Foo>>();
foo.foos->resize(8);

for (auto & f : *foo.foos) {
f.data = foo.data;
f.foos = foo.foos;
}
ptr = foo.data;
std::cout << "use count | inside: " << ptr.use_count() << '\n';

} //end scope

std::cout << "use count | after: " << ptr.use_count() << '\n';
}

输出是:

use count | before: 0
use count | inside: 10
use count | after: 9

这不好。我希望 use count | after成为1foo并且它的所有成员都应该在作用域结束时被解构。嗯,foo明确地被解构了(否则 use_count | after 将是 10 而不是 9 )但它的 .foos vector 指针未解构。和 ptr只是一个std::shared_ptr<int>因此与 struct Foo 无关根本。所有这些都可以通过提供 struct Foo 来解决。 reset() 的析构函数是 .foos->data手动指针:

#include <memory>
#include <iostream>
#include <vector>

struct Foo {
~Foo() {
for (auto& p : *foos) {
p.data.reset();
}
}

std::shared_ptr<int> data;
std::shared_ptr<std::vector<Foo>> foos;
};

int main() {
std::shared_ptr<int> ptr;
std::cout << "use count | before: " << ptr.use_count() << '\n';

{
Foo foo;
foo.data = std::make_shared<int>(5);
foo.foos = std::make_shared<std::vector<Foo>>();
foo.foos->resize(8);

for (auto & f : *foo.foos) {
f.data = foo.data;
f.foos = foo.foos;
}
ptr = foo.data;
std::cout << "use count | inside: " << ptr.use_count() << '\n';
}

std::cout << "use count | after: " << ptr.use_count() << '\n';
}

产生更好的输出:

use count | before: 0
use count | inside: 10
use count | after: 1

但是必须手动重置这些指针似乎很奇怪。为什么std::vectorstd::shared_ptr不会在这里自动执行?这是一个错误吗?


我正在使用 Visual Studio Community 2017 版本 15.9.5 - 感谢您的帮助!

最佳答案

问题是你有一个循环引用。

foo被销毁,它会减少其 shared_ptr引用计数 ,但这些不会达到零。

所以即使std::shared_ptr<std::vector<Foo>>是“无法访问”,上面还有指针。 (注意:垃圾收集器使用“可访问性”来收集/释放指针)。

打破循环的常用方法是使用std::weak_ptr .

关于c++ - 这个 std::vector 和 std::shared_ptr 内存泄漏是一个错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54437851/

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