Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Try to understand std::enable_shared_from_this<T> but cause a bad_weak_ptr using it

Tags:

c++

shared-ptr

I try to understand the behavior of std::enable_shared_from_this class, but I cant understand it. So I've write a simple program to test different situations.

Question

Can someone explain me the behavior of the following code, because I can't explain the observed result.

Thanks for you help.

Code

#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> { };

int main () {
    {//test 1
    std::shared_ptr<C> foo, bar;
    foo = std::make_shared<C>();
    bar = foo->shared_from_this(); //ok
    std::cout<<"shared_ptr : ok"<<std::endl;
    }

    {//test 2
    std::shared_ptr<C> foo = std::shared_ptr<C>(new C);
    std::shared_ptr<C> bar;
    bar = foo->shared_from_this(); //ok
    std::cout<<"shared_ptr + New : ok"<<std::endl;
    }

    {//test 3
    C* foo = new C;
    std::shared_ptr<C> bar;
    bar = foo->shared_from_this(); //throw std::bad_weak_ptr
    std::cout<<"New : ok"<<std::endl;
    }

   {//test 4 (should make a invalid free of something like that)
    C foo;
    std::shared_ptr<C> bar;
    bar = foo.shared_from_this();//throw std::bad_weak_ptr
    std::cout<<"local : ok"<<std::endl;
   }

  return 0;
}

And here is the output:

shared_ptr : ok
shared_ptr + New : ok
terminate called after throwing an instance of 'std::bad_weak_ptr'
   what():  bad_weak_ptr

Build Informations

  • System : Windows 7 x64
  • Compiler : mingw 4.9.2 x64
like image 819
Krozark Avatar asked Apr 01 '15 11:04

Krozark


2 Answers

The contract for enable_shared_from_this is that it will provide a shared_ptr when you call shared_from_this() if the object is managed by a shared_ptr. It cannot create a shared_ptr by itself if it is not already being managed.

You already figured out in the last test case why it would be a bad idea to allow shared_from_this() to create a shared pointer for you...

like image 98
David Rodríguez - dribeas Avatar answered Nov 11 '22 18:11

David Rodríguez - dribeas


If I remember correctly from the original boost documentation, "There must exist at least one shared_ptr instance p that owns t". For cases 3 and 4 there isn't at the point you call shared_from_this().

like image 39
Robinson Avatar answered Nov 11 '22 17:11

Robinson