有人可以解释为什么当内部范围退出时,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)
答案 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。
因为该指针有多个引用计数器,所以删除被多次调用。