简体   繁体   English

无法将 std::function 传递到 boost::asio async_accept 处理程序

[英]Unable to pass std::function into boost::asio async_accept handler

I am trying to write a server which takes a custom handler from the user using boost asio.我正在尝试编写一个服务器,它使用 boost asio 从用户那里获取一个自定义处理程序。 I am able to call statements from inside the async_accept handler but whenever I call the handler received by the server, It results in a segfault.我可以从 async_accept 处理程序内部调用语句,但是每当我调用服务器接收到的处理程序时,它都会导致段错误。

#include <boost/asio.hpp>
#include <functional>
#include <iostream>

using namespace std;
using namespace boost;
using boost::asio::ip::tcp;

class Server {
private:
  asio::io_service &io_service;
  tcp::acceptor acc;
  tcp::endpoint endpoint;

public:
  Server(asio::io_service &io) : io_service{io}, acc{io} {}

  void listen(unsigned short port);
  void accept(function<void()> handler);
};

void Server::listen(unsigned short port) {
  endpoint.port(port);

  acc.open(endpoint.protocol());
  acc.set_option(tcp::acceptor::reuse_address(true));

  acc.bind(endpoint);
  acc.listen();
}

void Server::accept(function<void()> handler) {
  tcp::socket socket(io_service);


  acc.async_accept(socket, [this, h = handler](const system::error_code &error) {
    cout << "Hello World" << endl;

    h();

    accept(h);
  });
}

int main() {
  asio::io_service io_service;
  Server s(io_service);

  s.listen(8000);

  s.accept([]() { cout << "Connection Accepted" << endl; });

  io_service.run();
}

However when I use std::bind to the lambda I pass it magically runs.但是,当我使用std::bind到 lambda 时,我通过它神奇地运行。 I am unable to understand why and would also like to know if this approach is performant?我无法理解为什么,也想知道这种方法是否有效?

void Server::accept(function<void()> handler) {
  tcp::socket socket(io_service);

  auto h = std::bind(handler);

  acc.async_accept(socket, [this, h](const system::error_code &error) {
    cout << "Hello World" << endl;

    h();

    accept(h);
  });
}

Problem is not with a handler.问题不在于处理程序。

Undefined behaviour is caused by accessing dangling reference to socket as local variable.未定义的行为是由将悬空引用作为局部变量访问socket引起的。

You call async_accept which takes the socket by reference as first parameter: According to official reference , the caller (you) is responsible to prolong its lifetime until handler is called:您调用async_accept ,它通过引用将套接字作为第一个参数:根据官方参考,调用者(您)有责任延长其生命周期,直到调用处理程序:

The socket into which the new connection will be accepted.接受新连接的套接字。 Ownership of the peer object is retained by the caller, which must guarantee that it is valid until the handler is called.对等体 object 的所有权由调用者保留,它必须保证在调用处理程序之前它是有效的。

You should wrap socket in some kind of smart pointer and then pass this pointer to lambda to prolong its lifetime:您应该将套接字包装在某种智能指针中,然后将此指针传递给 lambda 以延长其寿命:

  std::shared_ptr<tcp::socket> socket = std::make_shared<tcp::socket>(io_service);


  acc.async_accept(*socket, [this, h = handler, socket](const system::error_code &error) {

I hope, you are aware that async_XXX returns immediately, hence socket is deleted as well when the function returns.我希望,您知道async_XXX立即返回,因此当 function 返回时,套接字也会被删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM