这个std::vector和std::shared_ptr内存泄漏是一个bug吗
Is this std::vector and std::shared_ptr memory leakage a bug?
假设此类Foo
:
struct Foo {
std::shared_ptr<int> data;
std::shared_ptr<std::vector<Foo>> foos;
};
它有一个指向int 的指针
它有一个指向该程序中存在的所有实例的指针(因此其中一个实例==
*this
)
让我们创建一个Foo
的实例,并在向.foos
:添加一些实例后查看其.data
成员变量的use_count()
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()
返回时,似乎仍然会有98个指针指向.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
排除为1
,因为foo
及其所有成员应该在范围的末尾被解构。好吧,foo
被明确地解构了(否则use_count | after
将是10
而不是9
),但它的.foos
矢量指针没有被解构。并且CCD_ 22只是CCD_ 23,因此与CCD_ 24完全无关。所有这些都可以通过为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::vector
或std::shared_ptr
在这里不自动执行?是虫子吗?
我正在使用Visual Studio Community 2017 15.9.5版-感谢您的帮助!
问题是您有一个循环引用。
当foo
被破坏时,它会减少其shared_ptr
的引用计数,但这些计数不会达到零。
因此,即使std::shared_ptr<std::vector<Foo>>
是"不可访问"的,它上仍然有指针。(注意:垃圾收集器使用"可访问性"来收集/释放指针)。
打破循环的常用方法是使用std::weak_ptr
。
您创建了一个循环依赖项:每个Foo
都包含所有其他Foo
s的shared_ptr
s(即共享所有权)。这意味着任何Foo
都不会被销毁:要被销毁,use_count
必须为零。但在进入析构函数之前,它不能为零,因为每隔一个Foo
仍然保存一个引用。
这是共享所有权限制的经典案例——与一些观点相反,它并不能自动解决所有所有权问题。
我也会质疑每个Foo
存储指向所有Foo
s的相同指针的意义。如果这是你想要做的,它应该只是static
,但这听起来也不是一个好的设计。也许你可以详细说明你想要解决的实际问题(在一个新问题中)?
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 这个std::vector和std::shared_ptr内存泄漏是一个bug吗
- OS X libc++ std::uniform_real_distribution bug
- Clang bug with std::function, std::bind and std::ref?
- 奇怪的bug std::regex只匹配前两个字符串
- Boost lexical_cast<std::string>(int) MSVC 2008 bug
- 是否有Bug?Visual Studio 2013预览带有std::字符串的std::矢量初始值设定项列表
- 以下错误 C2248 的 bug 搜寻提示:'std::basic_ios<_Elem,_Traits>::basic_ios':无法访问类中声明的私有成员
- Visual C++ std::regex_search bug?
- c++中的Bug ?c++中的-set_difference不返回std::copy
- Bug in std::wstring?
- gcc7的std::变体实现中的Bug
- c++11 std::regex bug?
- Bug with std::deque?
- std::sort有可能导致bug吗?
- libc++ std::search_n中的崩溃是一个bug吗?
- QtConcurrent::blockingMapped() 和 std::vector<> bug
- 这是Mac OS X 10.6 c++ std API中的一个bug吗?