无法将 std::function 传递给 boost::asio async_accept 处理程序
Unable to pass std::function into boost::asio async_accept handler
我正在尝试编写一个服务器,它使用 boost asio 从用户那里获取自定义处理程序。我能够从 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();
}
然而,当我将 std::bind
用于我传递的 lambda 时,它神奇地运行了。我无法理解为什么,也想知道这种方法是否有效?
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);
});
}
问题不在于处理程序。
未定义的行为是由于将对 socket
的悬空引用作为局部变量进行访问而引起的。
您调用 async_accept
,它通过引用将套接字作为第一个参数:根据 official reference,调用者(您)负责延长其生命周期,直到调用处理程序:
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.
你应该用某种智能指针包装套接字,然后将这个指针传递给 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) {
我希望,您立即意识到 async_XXX
returns,因此当函数 returns 时 socket 也会被删除。
我正在尝试编写一个服务器,它使用 boost asio 从用户那里获取自定义处理程序。我能够从 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();
}
然而,当我将 std::bind
用于我传递的 lambda 时,它神奇地运行了。我无法理解为什么,也想知道这种方法是否有效?
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);
});
}
问题不在于处理程序。
未定义的行为是由于将对 socket
的悬空引用作为局部变量进行访问而引起的。
您调用 async_accept
,它通过引用将套接字作为第一个参数:根据 official reference,调用者(您)负责延长其生命周期,直到调用处理程序:
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.
你应该用某种智能指针包装套接字,然后将这个指针传递给 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) {
我希望,您立即意识到 async_XXX
returns,因此当函数 returns 时 socket 也会被删除。