C ++ shared_ptr继承内存泄漏

时间:2011-07-13 18:49:49

标签: c++ inheritance c++11 memory-leaks shared-ptr

我有一种情况,我有一个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进入系统,它就不会被销毁。有些事情正在停止被摧毁。

如果它与selfragent的几个容器shared_ptr有区别,那么当contains是destroy时,被调用的元素的析构函数是什么?

请让我知道我还能提供什么来解决问题。

3 个答案:

答案 0 :(得分:2)

在UserAgent中有一个dataRead std :: function,它最终被设置为一个包含std :: shared_ptr的lambda,以阻止它自我形式的破坏。我添加了一个close()方法并将std :: function设置为默认值。

现在一切都很顺利,它删除了很好的

感谢您的所有帮助

答案 1 :(得分:0)

我怀疑你的对象正在切片,但我没有可以测试的环境。

尝试以下方法之一:

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

答案 2 :(得分: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();
}