将 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