Asio 完成处理程序中的实例变量无效
Invalid instance variable in Asio completion handler
我已经使用 Asio(非增强)设置了一个简单的异步 tcp 服务器,它几乎遵循此处使用的代码:http://think-async.com/Asio/asio-1.11.0/doc/asio/tutorial/tutdaytime3.html
我遇到了一个问题,即尝试在 async_read_some/async_receive 的完成处理程序中访问当前 tcp_connection 实例的变量会引发错误。有问题的变量只是指向我创建的加密 class 实例的指针。一旦调用完成处理程序,该指针似乎就变得无效(0xFEEEFEEE 的地址)。这是从客户端建立连接后创建的 tcp_connection class:
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)。
有什么我想念的吗?我对 Asio 不太熟悉。提前致谢。
首先,当只有现存的异步操作时,你应该使用 shared_from_this
来防止 tcp_connection
变成 "collected":
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
class 应该实施三规则(至少在析构函数中清理 crypt_
并禁止 copy/assignment)。
您也没有释放当前示例中的 buf
。
当然,一般来说,这些都用智能指针就可以了。
我已经使用 Asio(非增强)设置了一个简单的异步 tcp 服务器,它几乎遵循此处使用的代码:http://think-async.com/Asio/asio-1.11.0/doc/asio/tutorial/tutdaytime3.html
我遇到了一个问题,即尝试在 async_read_some/async_receive 的完成处理程序中访问当前 tcp_connection 实例的变量会引发错误。有问题的变量只是指向我创建的加密 class 实例的指针。一旦调用完成处理程序,该指针似乎就变得无效(0xFEEEFEEE 的地址)。这是从客户端建立连接后创建的 tcp_connection class:
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)。
有什么我想念的吗?我对 Asio 不太熟悉。提前致谢。
首先,当只有现存的异步操作时,你应该使用 shared_from_this
来防止 tcp_connection
变成 "collected":
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
class 应该实施三规则(至少在析构函数中清理 crypt_
并禁止 copy/assignment)。
您也没有释放当前示例中的 buf
。
当然,一般来说,这些都用智能指针就可以了。