背景
采用Boost asio库发送RTP over TCP数据,调用asio::async_write(m_soc, asio::buffer(*data), std::bind(&rtsp_session::on_send, shared_from_this(), std::placeholders::_1, data, 0, std::placeholders::_2));发送数据。发送数据的过程中,客户端中断连接,产生10054的连接错误,这个时候,收到网络异常。
分析
网上说std::bad_weak_ptr这种错误是因为在构造函数中获取weakptr,此时对象还未构造,因此返回这样的异常。实际上
shared_from_this()实际上已经创建对象,并且没有销毁,因为没有调用析构函数。有没有可能是data已经释放了,也不可能。因为
std::shared_ptr<std::string> data = std::make_shared<std::string>((char*)rtp, rtp_size);这里最有可能的传参就是m_soc,因为在背景中提及该套接字句柄在客户端中断的时候,调用了close函数,但问题也不应该存在该变量,因为定义如下:asio::ip::tcp::socket m_soc
【引申】
enable_from_this 的使用与实现原理说明:
shared_from_this()是enable_shared_from_this<T>的成员函数,返回shared_ptr<T>;
注意的是,这个函数仅在shared_ptr<T>的构造函数被调用之后才能使用。
原因是enable_shared_from_this::weak_ptr并不在构造函数中设置,而是在shared_ptr<T>的构造函数中设置。
从引申中可以看出来是否是m_soc被认为没有初始化导致的问题,有这个可能,因为close的时候资源已经被释放了
使用说明
std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。
若一个类 T 继承 std::enable_shared_from_this<T> ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr<T> 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr<T> 对象,它与 pt 共享 t 的所有权。
使用原因
因为在异步调用中,存在一个保活机制,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。