我正在尝试使用 ASIO 实现一个简单的 TCP 服务器。这里的主要区别是我使用
std::unique_ptr
来保存缓冲区而不是原始指针,并且我将它们移动到完成处理程序中以延长其生命周期。
这是代码,它工作得很好(我猜)
void do_read() {
auto data = std::make_unique<uint8_t[]>(1500);
auto undesired_var = boost::asio::buffer(data.get(), 1500);
socket_.async_read_some(
undesired_var,
[self = shared_from_this(), data = std::move(data)](auto ec, auto len) mutable {
if (!ec) {
std::cout << "Received " << len << " bytes :)" << std::endl;
} else {
std::cout << "Read error: " << ec.message() << std::endl;
}
}
);
}
运行上面的代码,我得到以下输出:
/tcp_echo/cmake-build-debug/bin/tcp_server 6666
Received 9 bytes :)
请注意,我创建了一个名为
undesired_var
的变量来保存 boost::asio::mutable_buffer
数据。
当我尝试通过直接在 socket_.async_read_some
调用中创建这些变量来删除它们时:
void do_read() {
auto data = std::make_unique<uint8_t[]>(1500);
socket_.async_read_some(
boost::asio::buffer(data.get(), 1500),
[self = shared_from_this(), data = std::move(data)](auto ec, auto len) mutable {
if (!ec) {
std::cout << "Received " << len << " bytes :)" << std::endl;
} else {
std::cout << "Read error: " << ec.message() << std::endl;
}
}
);
}
我得到以下输出
tcp_echo/cmake-build-debug/bin/tcp_server 6666
Read error: Bad address
似乎在第二种情况下,我的
std::unique_ptr
过早地被破坏了,但我可以找出原因。我错过了什么吗?
是的,这是参数表达式的求值顺序。
std::move
可能会在您 .get()
之前发生。
此外,这里似乎有一个很大的问题:
auto data = std::make_unique<uint8_t>(1500);
动态分配一个无符号字符(
uint8_t
),它是从整数值1500
初始化的。分配的大小为 1(1 字节)。
auto undesired_var = boost::asio::buffer(data.get(), 1500);
您使用它时就好像它是 1500 字节一样。哎呀。您可能的意思是:
auto data = std::make_unique<uint8_t[]>(1500);
data
的类型现在是std::unique_ptr<uint8_t[], std::default_delete<uint8_t[]>>
,这是完全不同的模板专业化