2014-09-20 27 views
5

Ai đó có thể giải thích lý do tại sao các sự cố sau trong main() khi phạm vi bên trong bị thoát? Tôi đang sử dụng Visual Studio 2013. Mặc dù tất cả mọi thứ là tốt với GCC 4.8.1, tôi nghi ngờ một cái gì đó là sai trong mã anyway. Tôi chỉ không nhận được nó.Tai nạn bí ẩn với shared_ptr

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

Thông báo lỗi tôi nhận được với VS2013 là:

thất bại khẳng định

_BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

+0

Mã này khá nhỏ, tại sao không bước qua mã đó bằng trình gỡ lỗi? –

+0

@CaptainObvlious có thực sự hữu ích không? –

+0

@ n.m. Có lẽ không phải nhưng tôi là một masochist cho đến khi tôi đã có tô sáng của tôi của Fruity Pebbles. –

Trả lời

9

Bạn đang tạo nhiều trường hợp số tài liệu tham khảo cho cùng một con trỏ.
Tạo shred_ptr mới từ con trỏ bắt đầu bộ đếm tham chiếu mới. Khi một bộ đếm tham chiếu đạt đến 0, thì trình gỡ rối mặc định của shared_ptr sẽ xóa trên con trỏ đó.

Vì bạn có nhiều bộ đếm tham chiếu cho con trỏ đó, quá trình xóa được gọi nhiều lần.

13

Bạn có hai số shared_ptr s cố gắng sở hữu cùng một con trỏ (và chúng không biết về nhau). Điều này dẫn đến cả hai đều cố gắng giải phóng cùng một địa chỉ.

a đang cố gắng sở hữu tổng số this. Nhưng sau đó bạn vượt qua this đến CreateProxy() tạo một mớishared_ptr cố gắng nắm giữ tổng số quyền sở hữu là this. Số shared_ptr mới không biết về a, do đó, không ai chia sẻ số lượng tham chiếu của họ. shared_ptr s cần phải chia sẻ số lượng tham chiếu của họ, không chỉ là con trỏ.

Nếu bạn muốn chia sẻ một con trỏ giữa hai shared_ptr s, họ cần cả hai đều biết về nhau (để họ có thể cập nhật số tham chiếu của họ). Khi Girl gọi createProxy(), cần phải chuyển số shared_ptr đến this.

Có lẽ đây sẽ là thời điểm thích hợp để sử dụng std::enable_shared_from_this().

+0

Vì vậy, Girl phải lấy được từ std :: enable_shared_from_this và trong hàm tạo của nó gọi là 'createProxy (shared_from_this());' ? Điều đó có nghĩa là người phải có một quá tải createProxy (std :: shared_ptr )? – prestokeys

+0

@prestokeys: tại sao bạn sử dụng tất cả các công cụ proxy này. –

+0

@Cheers. Đó là một lời giải thích dài. Tôi đã xác nhận với một số lập trình viên chuyên nghiệp rằng nó là cần thiết cho chương trình của tôi. Nhưng tôi vẫn chưa sửa vấn đề trên bằng cách sử dụng std :: enable_shared_from_this (vẫn còn gãi đầu của tôi). – prestokeys