与shared_ptr的神秘崩溃

时间:2014-09-20 14:31:09

标签: 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.
}

我在VS2013上收到的错误信息是:

断言失败

_BLOCK_TYPE_IS_VALID(pHead-&GT; nBlockUse)

2 个答案:

答案 0 :(得分:13)

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

a正试图取得this的全部所有权。但是,您将this传递给CreateProxy(),这会创建一个 shared_ptr,试图获得this的全部所有权。新shared_ptr并不了解a,因此两人都不会分享他们的引用计数。 shared_ptr需要分享他们的引用计数,而不仅仅是指针本身。

如果你想在两个shared_ptr之间共享指针,他们需要彼此了解(因此他们可以更新他们的引用计数)。当Girl调用createProxy()时,需要将shared_ptr传递给this

也许这是使用std::enable_shared_from_this()的好时机。

答案 1 :(得分:9)

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

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