【问题标题】:Invalid instance variable in Asio completion handlerAsio 完成处理程序中的实例变量无效
【发布时间】:2015-04-10 09:32:36
【问题描述】:

我已经使用 Asio(非增强)设置了一个简单的异步 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 在内部使用线程的方式有关。不过,我会认为完成处理程序 (handle_receive) 会被当前的 tcp_connection 实例调用。

我有什么遗漏吗?我对Asio不太熟悉。提前致谢。

【问题讨论】:

    标签: c++ boost-asio


    【解决方案1】:

    首先,您应该使用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 类应该实现三规则(至少在析构函数中清理crypt_ 并禁止复制/赋值)。

    您也没有在当前示例中释放 buf

    当然,一般来说,对所有这些都使用智能指针。

    Live On Coliru

    【讨论】:

    • 我不敢相信它就像将“this”更改为“shared_from_this()”那么简单。非常感谢您的帮助 :) 至于您指出的其他事情,我正计划这样做,但没有因为我无法获得我必须按照应有的方式工作的代码。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    相关资源
    最近更新 更多