2014-09-20 26 views
5

Birisi iç kapsamı terk edildiğinde neden ana() 'de aşağıdaki çökmelerin nedenini açıklayabilir mi? Visual Studio 2013 kullanıyorum. GCC 4.8.1 ile her şey yolunda olsa da, yine de kodda bir şeylerin yanlış olduğundan şüpheleniyorum. Anlamadım.Shared_ptr ile gizemli çöküş

#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. 
} 

Ben VS2013 ile olsun hata iletisi:

onaylama işlemi hatası

_BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

+0

Kod oldukça küçük, neden bir hata ayıklayıcısını kullanarak adım atmıyorsunuz? –

+0

@CaptainObvlious gerçekten yardımcı olur muydu? –

+0

@ n.m. Muhtemelen hayır, ama benim meyveli çakıltaşımın sabah kasetini alana kadar mazoşistim. –

cevap

9

Aynı pointer için birden başvuru sayısı örneklerini yaratıyoruz.
İşaretçiden yeni bir shred_ptr oluşturmak yeni bir referans sayacı başlatır. Bir referans sayacı 0'a ulaştığında, shared_ptr'nin varsayılan silinmesi bu işaretçi üzerindeki silme işlemini çağırır.

o pointer için birden fazla referans sayacı Çünkü

, silme birden fazla kez denir.

13

Aynı işaretçi sahibi çalışan iki shared_ptr s var (ve onlar birbirleri hakkında bilmiyorum). Bu, her ikisinde de aynı adresi serbest bırakmaya çalışıyor.

a

this toplam sahipliğini almak için çalışıyor. Ama o zaman this toplam sahipliğini almak için çalışan bir yeni shared_ptr yaratan this CreateProxy() geçmektedir. Yeni shared_ptr, a hakkında bilgi sahibi değil, bu nedenle hiçbiri referans sayısını paylaşmıyor. shared_ptr s sadece referans işaretini değil, referans sayısını da paylaşmalıdır. İki shared_ptr s arasında bir işaretçi paylaşmak istiyorsanız

, ikisi de (böylece onların başvuru sayısı güncelleyebilir) birbirleri hakkında bilmemiz gerekir. Girl, createProxy()'u çağırdığında, shared_ptr değerini this'a iletmesi gerekir.

Belki de bu std::enable_shared_from_this() kullanmak için iyi bir zaman.

+0

Yani Kız std :: enable_shared_from_this 'dan ve yapıcı çağrısında 'createProxy (shared_from_this());' ? Kişinin bir createProxy (std :: shared_ptr ) aşırı yüklemesi olması gerektiği anlamına mı geliyor? – prestokeys

+0

@prestokeys: neden tüm bu proxy öğelerini kullanıyorsunuz? –

+0

@Cheers. Bu uzun bir açıklama. Bazı profesyonel programcılarla programım için gerekli olduğunu doğruladım. Ama yine de yukarıdaki problemi std :: enable_shared_from_this kullanarak (hala kafamı çizerek) düzeltmedim. – prestokeys