boost::asio::async_write缓冲区及const vector的销毁时机与位置问询
问题解答
1. 局部变量msg的销毁时机
const std::vector<char> msg是writeToSocketAsync函数内的局部栈变量,它的作用域仅局限于该函数内部。当writeToSocketAsync执行完毕、返回调用方时,栈上的msg会被自动销毁,其占用的内存会被操作系统直接回收。
2. async_write所用缓冲区(*tmsg)的销毁时机
tmsg是boost::shared_ptr<CharVec>类型的智能指针,它指向的vector对象(即异步写操作依赖的缓冲区)的生命周期由shared_ptr的引用计数决定:
- 在
writeToSocketAsync函数内创建tmsg时,该对象的引用计数为1; - 函数执行结束后,局部变量
tmsg被销毁,引用计数减1。这里要注意:你的代码没有把tmsg绑定到handle_write回调函数中,这会导致此时引用计数直接降到0,对应的vector对象会立刻被销毁。 - 但
async_write是异步操作,它大概率会在函数返回后才真正执行写逻辑,理论上此时已经出现了悬空引用的问题。你说代码能稳定处理数百万条消息,纯粹是巧合——比如异步调度刚好在函数返回前完成了写操作,或者内存未被立刻覆盖,但这种写法存在严重的安全隐患。
要修复这个问题,只需把tmsg绑定到回调函数中,让shared_ptr在异步操作期间保持引用计数大于0,修改后的bind代码如下:
strand_.wrap(boost::bind(&tcp_connection::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tmsg)) // 绑定tmsg以延长缓冲区生命周期
这样tmsg的引用计数会在回调函数存在期间保持为1,等handle_write执行完毕、回调被销毁后,引用计数才会降到0,缓冲区才会被安全销毁。
内容的提问来源于stack exchange,提问作者Al Kurlansky
相关产品推荐
相关产品推荐

