从不使用
new
delete
release
并且更喜欢使用
std::make_unique
std::unique_ptr
std::move
reset
(多余的)
应该道德导致没有内存泄漏:新的指针只能在智能指针中创建,从而无法逃脱,因为我们不允许使用release
除了C ++充满了令人讨厌的惊喜。根据我的假设反复粉碎的经验,我无法帮助,但我认为可能会有一些角落案件无论如何都会导致内存泄漏。更糟糕的是,可能有一种明显的方式来释放指针的所有权而不是release
本身。或者另一个智能指针类没有一个explicit
构造函数,它可能会意外地摄取通过get
获得的原始指针,导致双重释放......
有漏洞吗?如果有,可以通过添加一些更简单的限制来修复它们吗? (不分配任何内存都不算数!)如果可以达到一套防止所有类型内存错误的编码指南,那么完全忘记内存管理的细节是否可以?
答案 0 :(得分:5)
struct evil {
std::shared_ptr<evil> p;
};
void foo() {
auto e = std::make_shared<evil>();
e->p = e;
}
int main() {
for (unsigned i = 1; i != 0; ++i) {
foo();
if (i % 100000000)
std::cout << "I leak\n";
}
}
上述程序遵守您的限制,并像筛子一样泄漏。
最重要的是,未定义的行为可能会导致泄漏。
答案 1 :(得分:4)
我认为循环引用只是std::shared_ptr
...
struct X
{
std::unique_ptr<X> x;
};
void leak()
{
auto x = std::make_unique<X>();
x->x = std::move(x);
}
这可以通过确保在A
到B
之间添加边缘而形成的类型的图表中没有周期来解决,当且仅当A
包含成员{{ 1}}其中std::unique_ptr<C>
是C
的基础。
答案 2 :(得分:1)
可以完全忘记内存管理的细节吗?
我认为在可预见的未来,编程的答案将是 no 。即使在今天的垃圾收集语言中,如果您需要高性能应用程序,也不能忘记内存管理的细节。
当程序意外挂起不再需要的引用时,垃圾收集语言中仍会发生内存泄漏。遵循上面针对C ++制定的规则仍然会出现相同的问题,甚至更有可能成为使用shared_ptr
的问题。此类型的常见错误依赖于容器中的对象,或者通过垃圾收集语言中的托管引用的观察者或C ++中的shared_ptr
。
答案 3 :(得分:1)
没有保证,有太多人可以搞砸......
工会...... (Example)
union Devil {
std::unique_ptr<int> ptr;
int b;
Devil () {}
~Devil () {
// no idea what I'm doing
}
};
继承...... (Example)
struct Base {};
struct Derived : public Derived {
std::unique_ptr<int> ptr;
};
// later ...
std::unique_ptr<Base> p = std::make_unique<Derived>(42);
// oops
在筹码上玩......
int f1[10];
std::unique_ptr<int> p[2];
int f2[10];
// later ...
p[2] = std:: make_unique<int>(42);
// oops
...或更普遍的未定义行为。以上几点肯定只是冰山一角......