C ++ shared_ptr shared_from_this抛出bad_weak_ptr异常,即使我有一个引用它

时间:2016-06-17 22:53:14

标签: c++ boost-asio shared-ptr

编辑:我从来没有弄清楚这一点 - 我重构了与Boost示例完全相同的代码,但仍然存在问题。如果其他人有这个问题,那么当没有shared_ptr存在时(或在构造函数中),你的调用可能是更常见的shared_from_this()。否则,我建议只从boost asio示例重建。

我试图做一些我认为很常见的事情,但我遇到了一些问题。

我正在使用boost asio,并尝试创建TCP服务器。我接受与async_accept的连接,并创建共享指针。我有一个长期存在的对象(如连接管理器),它将shared_ptr插入到一个集合中。这是一个片段:

std::shared_ptr<WebsocketClient> ptr = std::make_shared<WebsocketClient>(std::move(s));
directory.addPending(ptr);
ptr->onConnect(std::bind(&Directory::addClient, &directory, std::placeholders::_1));
ptr->onDisconnect(std::bind(&Directory::removeClient, &directory, std::placeholders::_1));
ptr->onMessage(std::bind(&Directory::onMessage, &directory, std::placeholders::_1, std::placeholders::_2));
ptr->start();

目录有std::set<std::shared_ptr<WebsocketClient>> pendingClients;

添加客户端的功能是:

void Directory::addPending(std::shared_ptr<WebsocketClient> ptr){
    std::cout << "Added pending client: " << ptr->getName() << std::endl;
    pendingClients.insert(ptr);
}

现在,当WebsocketClient启动时,它尝试使用shared_from_this()创建shared_ptr,然后启动async_read_until(&#34; \ r \ n \ r \ n \ n&#34;),并将该shared_ptr传递给lambda保持所有权。它在实际调用asio函数之前崩溃,在shared_from_this()。

调用堆栈如下所示:

server.exe!WebsocketClient::start()
server.exe!Server::acceptConnection::__l2::<lambda>(boost::system::error_code ec)
server.exe!boost::asio::asio_handler_invoke<boost::asio::detail::binder1<void <lambda>(boost::system::error_code),boost::system::error_code> >(boost::asio::detail::binder1<void <lambda>(boost::system::error_code),boost::system::error_code> & function, ...)
server.exe!boost::asio::detail::win_iocp_socket_accept_op<boost::asio::basic_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::ip::tcp,void <lambda>(boost::system::error_code) ::do_complete(boost::asio::detail::win_iocp_io_service * owner, boost::asio::detail::win_iocp_operation * base, const boost::system::error_code & result_ec, unsigned __int64 __formal) Line 142  C++
server.exe!boost::asio::detail::win_iocp_io_service::do_one(bool ec, boost::system::error_code &)
server.exe!boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec)
server.exe!Server::run()
server.exe!main(int argc, char * * argv)

然而,当我调用shared_from_this时,我得到了bad_weak_ptr。我认为当没有shared_ptr拥有这个对象时抛出了这个,但是当我调用addPending时,我插入&#34; ptr&#34;进入一个集合,所以仍然应该有一个参考。

有什么想法吗?如果您需要更多详细信息,请询问,我会提供。这是我在StackOverflow上的第一篇文章,请让我知道我可以改进的内容。

2 个答案:

答案 0 :(得分:1)

你可能正在处理内存损坏问题。无论是否是这种情况,您都应该采取一些故障排除步骤:

  1. 记录从make_shared返回的指针值,并在调用shared_from_this之前再次在成员函数内部。检查运行对象表中是否存在该指针值(实际上是set<shared_ptr<...>>是什么)
  2. 仪器构造函数和析构函数。如果shared_ptr计数确实达到零,它将调用您的析构函数,调用堆栈将为您提供有关该问题的信息。
  3. 如果这没有帮助,那么您使用make_shared的事实应该是有用的,因为它可以保证元数据块就在对象旁边。

    1. 使用memcpy在不同时间转储对象前面的原始字节,并注意潜在的损坏。
    2. 大部分日志记录都会在显示未定义行为的上下文中发生。如果编译器发现你正在测试一些不可能的东西,它实际上可能会删除测试。在这种情况下,您通常可以通过精确使用#pragma来管理测试,以便仅在调试日志代码上禁用优化 - 您不希望更改其余代码的优化设置,因为这可能会改变腐败的表现方式,而不会实际修复它。

答案 1 :(得分:1)

如果没有代码,很难确定问题的原因。 但是你用enable_shared_from_this哪个,提升还是标准? 我看到你使用std::make_shared,所以如果WebsocketClient继承boost::enable_shared_from_this,它可能会导致崩溃。