将 unique_ptr 传递给完成处理程序时出现 Boost ASIO "Bad address" 错误
Boost ASIO "Bad address" error when passing unique_ptr to completion handler
我正在尝试使用 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[]>>
即 an entirely different template specialization
我正在尝试使用 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[]>>
即 an entirely different template specialization