Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

double free or corruption with shared pointers

Tags:

c++

pointers

So the essence of my problem is this:

//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
};

Compiles fine but it gives a "double free or corruption" when exiting main (in the full program this is just a sub function)

I suspect the shared_ptr to big is being freed at some point and then again when exiting main, but I'm not sure and have no idea of how to fix it. Can someone please explain to me the reason of this error?

I red that I had to NULL the pointer to but I don't know where. Or maybe I'm just using the wrong smart pointer or something like that?

Thanks

like image 861
Purin Lord Avatar asked Oct 11 '16 22:10

Purin Lord


People also ask

How do you avoid double free in C++?

Double Free A simple technique to avoid this type of vulnerability is to always assign NULL to a pointer after it has been freed. Subsequent attempts to free a null pointer will be ignored by most heap managers.

What is the point of shared pointers?

In C++, a shared pointer is one of the smart pointers. The shared pointer maintains a reference count which is incremented when another shared pointer points to the same object. So, when the reference count is equal to zero (i.e., no pointer points to this object), the object is destroyed.

What is the difference between shared pointer and weak pointer?

The only difference between weak_ptr and shared_ptr is that the weak_ptr allows the reference counter object to be kept after the actual object was freed. As a result, if you keep a lot of shared_ptr in a std::set the actual objects will occupy a lot of memory if they are big enough.

What happens when you move a shared pointer?

By moving the shared_ptr instead of copying it, we "steal" the atomic reference count and we nullify the other shared_ptr . "stealing" the reference count is not atomic, and it is hundred times faster than copying the shared_ptr (and causing atomic reference increment or decrement).


2 Answers

You're constructing a shared_ptr with a pointer to an existing object on the stack. Don't do that; that's not how shared_ptr is meant to be used. Ordinary stack objects should never be deleted or freed. The object it's pointing at is supposed to be on the heap, i.e. created using new or the equivalent.

The recommended way to create a shared_ptr is through make_shared:

auto p = make_shared<Big>();

or the old-fashioned way:

shared_ptr<Big> p(new Big);
like image 146
Ross Smith Avatar answered Sep 27 '22 20:09

Ross Smith


Objects managed by a shared_ptr must be constructed in dynamic scope, i.e. allocated with new.

Big big;
big.a = 100;
big.b = 200;

Mini derp(5, shared_ptr<Big>(&big));

And here, you're shoving a pointer to an object that was constructed in automatic scope into a shared_ptr. shared_ptr now thinks it owns this object, and it gets to decide when it is going to delete it.

But when this object in automatic scope goes out of scope and gets destroyed, this will make this shared_ptr very, very sad.

Use new to construct this object, instead of constructing it in automatic scope.

like image 34
Sam Varshavchik Avatar answered Sep 27 '22 19:09

Sam Varshavchik