C++ shared_ptr继承内存泄漏
我遇到的情况是,我有一个子类的基类的shared_ptr。
当shared_ptr去删除指针时,只有父析构函数被调用。
父母的析构函数是虚拟的,孩子的不是,尽管我已经尝试了所有组合。
我在 valgrind 中有该程序,它显示在创建对象时在 new 语句中创建了内存。我知道父析构函数被调用,但子析构函数没有被调用。
这是孩子:
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;
}
编辑: 我做了更多的测试,恐怕问题比我希望的要复杂。当项目被销毁时,析构函数就会被调用,但是问题是,一旦 UserAgent 进入系统,它就不会被销毁。有些东西正在阻止被破坏。
如果有区别的话,shared_ptr 的几个容器到用户代理,当一个容器被销毁时,内部元素的析构函数会被调用吗?
请让我知道我还能提供什么来解决该问题。
I have a situation where I have a shared_ptr to base of a child class.
When the shared_ptr goes to delete the pointer, only the parent destructor is being called.
The parents destructor is virtual, the childs is not, although I have experimented in all combinations.
I have the program in valgrind, and it show that memory is created at the new statement when object created. And I know the parent destructor is being called, but the child's isn't.
this is the child:
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;
};
the parent:
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;
};
Usage:
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.
Thank You.
Also please note the code above is still a work in process.
EDIT: I was wrong the child destructor is being called,
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:
I have done more testing and I am afraid the problem is complex than I hoped. The destructors are being called when the items are being destroyed however, the issue is once the UserAgent enters the system it doesn't get destroyed. Something is stopping from being destroyed.
if it makes and difference the are several containers of shared_ptr to the useragent, when a contain is destroy are the destructors of the elements inside called?
Please let me know what else I can provide to fix the problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
UserAgent 中有一个 dataRead std::function ,它最终被设置为一个包含 std::shared_ptr 的 lambda,以阻止其自我破坏。我添加了一个 close() 方法并将 std::function 设置为其默认值。
现在一切都很好并且删除得很好
感谢您的帮助
There was a dataRead std::function in UserAgent which ended up getting set to a lambda containing a std::shared_ptr to itself stopping it self form destructing. I added a close() method and set the std::function to it default value.
Now all is well and it delete fine
Thanks for all your help any way
我怀疑你的对象正在被切片,尽管我没有环境可以测试。
尝试以下其中一项:
I suspect your object is being sliced, though I don't have an environment to test.
Try one of these:
在
void Server::reset()
中auto_ptr
就足够了。在第二种情况下,我会执行以下操作:
In
void Server::reset()
auto_ptr
is enough.In second case I would do the followings: