【问题标题】:bad_weak_ptr with boost smart pointerbad_weak_ptr 与 boost 智能指针
【发布时间】:2019-05-16 15:47:37
【问题描述】:

我用 boost asio 和 beast 开发了一个桌面聊天(用于浏览器支持)。

我使用这种架构:

但是,在构建时,我有一个问题:bad_weak_ptr,我不知道出了什么问题:s 这里是源的链接 https://onlinegdb.com/BkFhDGHe4

更新1: 我将 run() 函数删除到构造函数中,并将其移动到 handle_accept 函数、tcp_server 类中。像这样:

void tcp_server::handle_accept(const boost::system::error_code ec, websocket_session_ptr new_websocket) { if (!ec) { // Happens when the timer closes the socket if(ec == boost::asio::error::operation_aborted) return; new_websocket->run(); //Here chatwebsocketsessionpointer session = chat_websocket_session::create(room, new_websocket); room->join(session); wait_for_connection(); } } 我可以看到 chat_webocket_session 已删除,但bad_weak_ptr 仍然存在问题

更新 2: 我发现问题出在哪里。 如果我从不调用 do_read() 函数,则没有错误,我可以使用 ws 连接到服务器 如果我从 chat_websoket_session 类中将它调用到 wait_for_data 中,我就有问题了。 所以我必须找到如何调用 do_read()

更新 3: 如果我做 websocket_session_ptr new_websocket(new websocket_session(std::move(socket))); acceptor.async_accept( socket, boost::bind( &tcp_server::websocket_accept, this, boost::asio::placeholders::error, new_websocket ));

引用:boost beast websocket example,我首先接受套接字,然后用m_ws.async_accept() 接受 websocket,但我现在有了Bad file descriptor,这意味着套接字未打开。

P.S:我更新了ide URL(GDB在线调试器)

【问题讨论】:

  • 不要使用漂亮的图表——它不会告诉我们任何关于代码的信息,而是将您的代码减少到显示问题的最少代码,并将其包含在问题中。你的问题是关于代码,而不是 OOP 设计
  • 你得到accept: operation cancelled,因为你正在调用async_accept,而套接字被移到了上一行。 std::move(socket) 变成 new_websocket。移动后socket 没用,不应该传给async_accept。
  • 如果我将 run() 移动到 wait_for_data() 或 chat_websocket_session 类的构造函数中,我也会遇到同样的问题
  • 如果我从 websocket_session 构造函数中删除 std::move(socket) 和 websocket_session_ptr new_websocket(new websocket_session(socket)); 我有 use of deleted function

标签: c++ networking boost-asio boost-beast


【解决方案1】:

您在构造函数内部使用指向 this 的共享指针:

websocket_session::websocket_session(tcp::socket socket)
        : m_ws(std::move(socket))
        , strand(socket.get_executor())
{
    run();
}

run() 里面你做

void websocket_session::run() {
    // Accept the websocket handshake
    std::cout << "Accepted connection" << std::endl;
    m_ws.async_accept(boost::asio::bind_executor(
        strand, std::bind(&websocket_session::on_accept, , std::placeholders::_1)));
}

使用shared_from_this(),它将尝试从enable_shared_from_this 锁定未初始化的weak_ptr。正如您在引发std::bad_weak_ptr 异常的documentation 中看到的(广告11)

shared_from_this 的文档明确警告这一点:

只允许在先前共享的对象上调用 shared_from_this,即在 std::shared_ptr 管理的对象上(特别是,shared_from_this 不能在构造函数中调用)。

【讨论】:

  • 我从构造函数中删除了 run() 函数,并将该函数调用到 wait_for_data() 函数中(chat_websocket_session 类)。我还有问题。
  • 使run 成为单独调用的成员函数的全部意义正是因为您不能在构造函数中调用shared_from_this :)
  • 审核您从weak_ptr 构造shared_ptr 的所有情况,包括对shared_from_this 的所有调用。确保在对象完全构造之前或在调用其析构函数之后无法调用它们。你也可以只使用一个可以在抛出时中断的调试器,看看是什么代码在做它。
  • 我将 shared_from_this() 更改为 this 到 websocket_session() 绑定函数,它解决了问题,但现在我有accept : operation canceled
  • @Vana 很幸运,因为它可以保护您免受未定义行为的影响。 operation aborted 是 Io 对象实例被破坏的自然结果
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多