2011-07-13 42 views
1

我有一个情况,我有一个shared_ptr基类的子类。C++ shared_ptr继承内存泄漏

当shared_ptr去删除指针时,只有父析构函数被调用。

父母的析构是虚拟的,孩子不是,虽然我已经在所有组合中进行了实验。

我有valgrind中的程序,它显示内存是在创建对象时在新语句中创建的。我知道父析构函数正在被调用,但孩子的不是。

这是孩子:

class NetworkUserAgent : public bbs::UserAgent 
{ 
friend class Server; 

public: 
    NetworkUserAgent(boost::asio::io_service &ioService, size_t _szBuffer=512u); 
    ~NetworkUserAgent(); 

    void asyncRead(); 
    void doneRead(std::shared_ptr< std::vector<char> > pBuf, 
        const boost::system::error_code &error, size_t byTrans); 

    void writeTo(const std::string &msg); 
    void doneWrite(const boost::system::error_code &error, size_t byTrans); 

void close(); 

private: 
    boost::asio::ip::tcp::socket socket_; 
    const size_t szBuffer; 
}; 

父:

class UserAgent 
{ 
public: 
    //'structors 
    UserAgent(); 
    virtual ~UserAgent(); 

    //commication 
    virtual void writeTo(const std::string &msg)=0; 
    std::function<void(std::string&)> dataRead; 

    //user management 
    void login(AccessLevel _accessLevel, int userId, const std::string &_userName); 
    void logout(); 

    //Accessors 
    AccessLevel UserAccessLevel() const; 
    const std::string &UserName() const; 
    const int &UserId() const; 
    bool LoggedIn() const; 

    //shared to allow reference to child type 
    std::shared_ptr<ContextAgentData> contextAgentData; 
private: 
    std::string userName; 
    int userId; 

    AccessLevel accessLevel; 
}; 

用法:

void Server::reset() 
{ 
    shared_ptr<NetworkUserAgent> client (new NetworkUserAgent(ioService)); 
    acceptor_.async_accept(client->socket_, 
     [=] (const boost::system::error_code &error) 
      { this->clientAccepted(client, error); } 
     ); 
} 

void Server::clientAccepted(shared_ptr<NetworkUserAgent> client, 
           const boost::system::error_code &error) 
{ 
    if(error) return; 
    cout << "[] New client has connected" << endl; 

    //Generalise to Network useragent 
    shared_ptr<UserAgent> uaClientPtr=client; 
    context->receiveUserAgent(uaClientPtr); 
    client->asyncRead(); 
    reset(); 
} 

The rest of the code can be seen here

谢谢。

另外请注意上面的代码仍然是一个在工作中。

编辑:我错了孩子的析构函数被调用,

NetworkUserAgent::~NetworkUserAgent() 
{ 
    this->close(); 
} 

void NetworkUserAgent::close() 
{ 
    if(!socket_.is_open()) return; //socket is already closed 
    //one or more of these functions are probably redundant 
    cout << "send request" <<endl; 
    socket_.shutdown(ip::tcp::socket::shutdown_send); 
    cout << "cancel" <<endl; 
    socket_.cancel(); 
    cout <<"close"<<endl; 
    socket_.close(); 
    cout << "done" <<endl; 
} 

编辑: 我做更多的测试,我恐怕这个问题是复杂的比我希望的。当物品被销毁时,析构函数会被调用,但问题是一旦UserAgent进入系统,它不会被销毁。有些东西正在被摧毁。

如果它使得和差异是几个容器的shared_ptr到useragent,当一个包含摧毁是内部调用的元素的析构函数?

请让我知道我可以提供什么来解决这个问题。

+1

它不是从问题的代码贴清醒时共享指针应予以删除。我查看了链接中的代码(顺便提一下),那里的代码太多了。你能否详细说明你希望何时删除共享指针?你怎么确定孩子的析构函数没有被调用(它不记录父类的东西)? – Chad

+1

只是为了显示'std :: shared_ptr'正确处理这种情况的简单示例:http://ideone.com/TRXVu。我不得不第二个乍得关于你是否确定正确的析构函数没有被调用的问题? –

+0

请提供可复制的可运行代码来重现问题。切片出现在您已省略的代码中的某处非常有可能。 –

回答

2

有在UserAgent的一个DATAREAD的std ::功能,最终得到设置为包含一个std一个lambda :: shared_ptr的本身停止它的自我形式自毁。我添加了一个close()方法并将std :: function设置为默认值。

现在一切都很好,它删除精细

感谢您的帮助,任何方式

0

我怀疑你的对象被切片了,虽然我没有一个测试环境。

尝试其中之一:

shared_ptr<UserAgent> uaClientPtr = boost::static_pointer_cast<UserAgent>(client); 
shared_ptr<UserAgent> uaClientPtr = boost::dynamic_pointer_cast<UserAgent>(client); 
+0

这会更安全,但在这里是不必要的,因为这两种类型已知彼此继承。不应发生切片。 –

0

void Server::reset()auto_ptr就足够了。

在第二种情况下,我会做以下内容:

void Server::clientAccepted(shared_ptr<NetworkUserAgent> client, const boost::system::error_code error) 
{ 
    if(error) return; 
    cout << "[] New client has connected" << endl; 
    context->receiveUserAgent(client); 
    client->asyncRead(); 
    this->reset(); 
} 
+0

这很整洁,但问题仍然存在 – 111111