Mysterious crash with shared_ptr

Can someone explain why the following failures in main () when exiting the inner area? I am using Visual Studio 2013. Although everything is fine with GCC 4.8.1, I suspect that something is wrong in the code anyway. I just do not understand.

#include <iostream> #include <memory> class Person; class PersonProxy; class PersonInterface { public: virtual ~PersonInterface() = default; virtual PersonProxy* getProxy() const = 0; virtual void createProxy (Person*) = 0; }; class Person : public PersonInterface { private: std::string name; std::shared_ptr<PersonProxy> proxy; public: Person() = default; explicit Person (const std::string& n) : name(n) {} public: virtual PersonProxy* getProxy() const override {return proxy.get();} inline void createProxy (Person* p); }; class PersonProxy : public PersonInterface { private: std::shared_ptr<Person> actual; public: explicit PersonProxy (Person* p) : actual (std::shared_ptr<Person>(p)) {} explicit PersonProxy (std::shared_ptr<Person> p) : actual (p) {} void rebind (std::shared_ptr<Person> p) {actual = p;} virtual PersonProxy* getProxy() const override {return actual->getProxy();} virtual void createProxy (Person* p) override {actual->createProxy(p);} }; class Girl : public Person { public: Girl (const std::string& name) : Person (name) {createProxy (this);} }; inline void Person::createProxy (Person* p) { proxy = std::shared_ptr<PersonProxy>(new PersonProxy(p)); } int main() { { Girl* a = new Girl("a"); // std::shared_ptr<Girl> a = std::make_shared<Girl>("a"); // Using this crashes with Visual Studio 2013 on the line 'a->getProxy()->rebind(b);' std::shared_ptr<Girl> b = std::make_shared<Girl>("b"); a->getProxy()->rebind(b); std::cout << "rebind succeeded." << std::endl; } std::cout << "Exited scope." << std::endl; // Exiting scope crashes with VS 2013. } 

The error message I get with VS2013:

Approval Error

_BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

+5
source share
2 answers

You have two shared_ptr trying to own the same pointer (and they do not know about each other). This causes both of them to try to free the same address.

a trying to completely own this . But then you pass this to CreateProxy() , which creates a new shared_ptr that tries to completely own this . The new shared_ptr does not know about a , so not one of them shares its reference count. shared_ptr needs to split the reference count, not just the pointer itself.

If you want to split the pointer between two shared_ptr s, they must know about each other (so that they can update the reference count). When Girl calls CreateProxy() , he needs to pass shared_ptr to this .

Perhaps this would be a good time to use std::enable_shared_from_this() .

+13
source

You create multiple link instances for the same pointer.
Creating a new shred_ptr from a pointer starts a new reference counter. When the reference counter reaches 0, the release default of shared_ptr will delete this pointer.

Since you have more than one reference counter for this pointer, deletion is called more than once.

+9
source

Source: https://habr.com/ru/post/1203038/


All Articles