共享指针的双自由度或损坏

double free or corruption with shared pointers

本文关键字:损坏 自由度 指针 共享      更新时间:2023-10-16

所以我的问题的本质是:

//Big.h
class Big{
    public:
        int a, b;
};
//Mini.h
class Big;
class Mini{
    public:
        Mini(float a, shared_ptr<Big> ptb):ma(a), me(-a), ptb(ptb){};
        float ma, me;
        shared_ptr<Big> ptb;
};
//main
int main(){
    std::list<Mini> lm;
    if(true){ //Or some sub function or rutin
        Big big; big.a = 100; big.b = 200;
        Mini derp(5, shared_ptr<Big>(&big));
        lm.push_front(derp);
    }
  //Do something
};

编译得很好,但是当退出main(在完整的程序中这只是一个子函数)时,它给出了一个"双自由或损坏"

我怀疑shared_ptrbig在某个时候被释放,然后在退出main时再次被释放,但我不确定,也不知道如何修复它。有人能给我解释一下这个错误的原因吗?

我认为我必须NULL的指针,但我不知道在哪里。或者我只是用错了智能指针之类的?

谢谢

您正在使用指向堆栈上现有对象的指针构建shared_ptr。不要那样做;这不是shared_ptr的使用方式。普通的堆栈对象永远不应该被删除或释放。它指向的对象应该在堆上,即使用new或等效的方法创建。

创建shared_ptr的推荐方法是通过make_shared:

auto p = make_shared<Big>();

或传统方式:

shared_ptr<Big> p(new Big);

shared_ptr管理的对象必须在动态范围内构造,即分配给new

Big big;
big.a = 100;
big.b = 200;
Mini derp(5, shared_ptr<Big>(&big));

在这里,你把一个指向在自动作用域内构造的对象的指针推入shared_ptrshared_ptr现在认为它拥有这个对象,并且它可以决定何时将它交给delete

但是当自动作用域中的对象超出作用域并被销毁时,这将使shared_ptr非常非常悲伤。

使用new来构造这个对象,而不是在自动作用域中构造。

shared_ptr指向一个堆栈对象。不能释放堆栈对象。以下是如何使用shared_ptr:

auto big = std::make_shared<Big>();
big->a = 100;
big->b = 200;
Mini derp(5, big);

要纠正程序,需要在堆上分配Big对象。

if(true){ //Or some sub function or rutin
        auto big_shared_ptr = std::make_shared<Big>();
        big->a = 100; big->b = 200;
        Mini derp(5, big_shared_ptr);
        lm.push_front(derp);
    }

这样,当if(true)块返回以及shared_ptr被清理时,变量不会被销毁——这将导致double free。