与shared_ptr的神秘崩溃

pre*_*eys 5 c++ shared-ptr

有人可以解释为什么当内部范围退出时,main()中的以下崩溃?我正在使用Visual Studio 2013.虽然GCC 4.8.1的一切都很好,但我怀疑代码中有问题.我只是不明白.

#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.
}
Run Code Online (Sandbox Code Playgroud)

我用VS2013得到的错误信息是:

断言失败

_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)

Cor*_*lks 13

你有两个shared_ptr试图拥有相同的指针(他们彼此不知道).这导致他们两个都试图释放相同的地址.

a正试图取得全部所有权this.但是然后你传递thisCreateProxy()了一个新的 shared_ptr,试图获得全部所有权this.新的shared_ptr不知道a,所以没有人分享他们的参考计数.shared_ptr需要分享他们的引用计数,而不仅仅是指针本身.

如果你想在两个shared_ptrs 之间共享指针,他们需要彼此了解(因此他们可以更新他们的引用计数).当Girl调用createProxy(),它需要通过一个shared_ptrthis.

也许这将是一个使用的好时机std::enable_shared_from_this().


Yoc*_*mer 9

您正在为同一指针创建多个引用计数实例.
从指针创建新的shred_ptr会启动一个新的引用计数器.当引用计数器达到0时,shared_ptr的默认删除器调用该指针上的delete.

因为该指针有多个引用计数器,所以删除被多次调用.