C++ Boost.Asio异步回调选lambda还是boost::bind?lambda捕获问题如何解决
问题根因
lambda写法失效的核心原因是仅捕获裸this没有持有connection对象的shared_ptr强引用,异步操作还未完成时对象可能已经被析构,导致野指针访问。而boost::bind写法因为绑定了this->shared_from_this(),会让异步回调持有对象的强引用,只要回调未执行完毕引用计数就不会归零,对象不会提前释放。
解决方案
修改lambda的捕获逻辑,让其持有shared_from_this()返回的强引用即可,分两种兼容写法:
C++14及以上版本(支持广义捕获)
void read() { if (!socket_.is_open()) { std::cout << "[ERROR] socket_ is not open\n"; return; } std::fill_n(read_buffer_, MAX_MSG, '\0'); async_read(socket_, boost::asio::buffer(read_buffer_), [self = this->shared_from_this()](const err& error, size_t bytes)->size_t { if (error) { return 0; } bool found = std::find(self->read_buffer_, self->read_buffer_ + bytes, '\n') < self->read_buffer_ + bytes; return found ? 0 : 1; }, [self = this->shared_from_this()](const err& error, size_t bytes)->void { if (!self->started_) { return; } if (error) { std::cout << "[ERROR] async_read\n" << error.message(); self->stop(); return; } std::string msg(self->read_buffer_, bytes); self->on_message(msg); }); }
C++11兼容版本
void read() { if (!socket_.is_open()) { std::cout << "[ERROR] socket_ is not open\n"; return; } std::fill_n(read_buffer_, MAX_MSG, '\0'); // 提前定义局部变量持有强引用,再传入lambda捕获 auto self = this->shared_from_this(); async_read(socket_, boost::asio::buffer(read_buffer_), [self](const err& error, size_t bytes)->size_t { if (error) { return 0; } bool found = std::find(self->read_buffer_, self->read_buffer_ + bytes, '\n') < self->read_buffer_ + bytes; return found ? 0 : 1; }, [self](const err& error, size_t bytes)->void { if (!self->started_) { return; } if (error) { std::cout << "[ERROR] async_read\n" << error.message(); self->stop(); return; } std::string msg(self->read_buffer_, bytes); self->on_message(msg); }); }
选型建议
- 优先选lambda:语法直观,逻辑集中无需额外定义成员函数,编译期参数检查更严格,报错信息比
boost::bind清晰很多,适合回调逻辑仅在当前异步操作使用、不需要复用的场景,是目前Asio开发的主流写法。 - 优先选
boost::bind:适合回调逻辑可复用、多个异步操作共用同一段处理逻辑的场景,可减少重复代码,对C++11之前的老项目兼容性更好。 - 通用规则:两种写法都必须保证回调执行期间对象生命周期有效,长连接异步场景下不要仅捕获裸
this,必须通过绑定/捕获shared_from_this()持有强引用,避免对象提前析构导致野指针问题。
内容的提问来源于stack exchange,提问作者Chris Redwood
相关产品推荐
相关产品推荐

