Asio完成处理程序中的实例变量无效

Invalid instance variable in Asio completion handler

本文关键字:实例 变量 无效 程序 处理 Asio      更新时间:2023-10-16

我已经使用Asio(非boost)设置了一个简单的异步tcp服务器,它基本上遵循这里使用的代码:http://think-async.com/Asio/asio-1.11.0/doc/asio/tutorial/tutdaytime3.html

我遇到一个问题,试图访问async_read_some/async_receive的完成处理程序中当前tcp_connection实例的变量时会引发错误。有问题的变量只是指向我创建的加密类实例的指针。一旦调用完处理程序,这个指针似乎就无效了(0xFEEEFEEE的地址)。以下是tcp_connection类,该类在与客户端建立连接后创建:

class tcp_connection
    : public enable_shared_from_this<tcp_connection> {
public:
    typedef shared_ptr<tcp_connection> pointer;
    static pointer create(asio::io_service &ios) {
        return pointer(new tcp_connection(ios));
    }
    tcp::socket &socket() {
    return socket_;
    }
    void start() {
        byte* buf = new byte[4096];
        socket_.async_receive(asio::buffer(buf, 4096), 0,
            bind(&tcp_connection::handle_receive, this,
            buf,
            std::placeholders::_1, std::placeholders::_2));
    }
private:
    tcp_connection(asio::io_service &ios)
        : socket_(ios) {
        crypt_ = new crypt();
    }
    void handle_receive(byte* data, const asio::error_code &err, size_t len) {
        cout << "Received packet of length: " << len << endl;
        crypt_->decrypt(data, 0, len);  // This line causes a crash, as the crypt_ pointer is invalid.
        for (int i = 0; i < len; ++i)
            cout << hex << setfill('0') << setw(2) << (int)data[i] << ", ";
        cout << endl;
    }
    tcp::socket socket_;
    crypt* crypt_;
};

我认为这与Asio在内部使用线程的方式有关。不过,我本以为会使用当前tcp_connection实例调用完成处理程序(handle_receive)。

我缺了什么吗?我对阿西奥不太熟悉。提前谢谢。

首先,当只有现存的异步操作时,应该使用shared_from_this来防止tcp_connection被"收集":

    socket_.async_receive(asio::buffer(buf, 4096), 0,
        bind(&tcp_connection::handle_receive, shared_from_this()/*HERE!!*/, 
        buf,
        std::placeholders::_1, std::placeholders::_2));

其次,tcp_connection类应该实现Rule Of Three(至少清除析构函数中的crypt_并禁止复制/赋值)。

您在当前样本中也没有释放buf

当然,一般来说,只需对所有这些使用智能指针即可。

在Coliru上直播