Утечка памяти в C ++ shared_ptr - PullRequest
1 голос
/ 13 июля 2011

У меня есть ситуация, когда у меня есть 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();
}

Остальной код можно увидеть здесь .

Спасибо.

Также обратите внимание, что приведенный выше код все еще находится в процессе разработки.

РЕДАКТИРОВАТЬ: Я был неправ, вызывается дочерний деструктор,

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;
}

EDIT: Я сделал больше испытаний, и я боюсь, что проблема сложная, чем я надеялся. Деструкторы вызываются, когда элементы уничтожаются, однако проблема заключается в том, что когда агент UserAgent входит в систему, он не уничтожается. Что-то мешает быть уничтоженным.

если это имеет значение и различать несколько контейнеров shared_ptr для useragent, когда контейнер уничтожен, называются деструкторы элементов внутри?

Пожалуйста, дайте мне знать, что еще я могу предоставить для решения проблемы.

Ответы [ 3 ]

2 голосов
/ 14 июля 2011

В UserAgent была функция dataRead std :: function, которая в конечном итоге была установлена ​​в лямбду, содержащую std :: shared_ptr, что останавливало ее самоуничтожение.Я добавил метод close () и установил в std :: function значение по умолчанию.

Теперь все в порядке, и он отлично удаляется

Спасибо за вашу помощь в любом случае

0 голосов
/ 13 июля 2011

В 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 голосов
/ 13 июля 2011

Я подозреваю, что ваш объект нарезается, хотя у меня нет среды для тестирования.

Попробуйте один из них:

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