4

我正在使用 boost::asio。我编写了一个负责从套接字异步读取的类。在我的应用程序中,io_service 可以在一个应用程序运行期间多次停止和启动。所以我不得不担心服务停止时内存泄漏。我想到了两个解决方案:

  1. 一个请求异步请求的类为函数提供了一个在 asio 读取中使用的缓冲区,并且它负责释放它。这是一个明显的解决方案,但我不喜欢它。将不需要的参数传递给函数看起来很奇怪。

  2. 绑定到回调的智能指针。此处示例:http: //pastebin.com/p8nQ5NFi

现在我正在使用第二种解决方案,但无论我感觉如何,我正在发明一个轮子。异步调用中缓冲区清理的常见做法是什么?我的方法有什么隐藏的问题吗?

4

1 回答 1

4

这种shared_ptr方法相当普遍。但是,不是将 ashared_ptr作为附加参数传递给bind,而是可以将shared_ptr作为实例对象传递来代替this

boost::shared_ptr< my_class > ptr( this );

boost::asio::async_read( stream, buffer, 
  boost::bind( &my_class::read_handler, ptr, 
     boost::asio::placeholders::error
     boost::asio::placeholders::bytes_transferred ) );

通常,由于实例将通过 a 进行管理shared_ptr,它可能在也可能不在 的上下文中this,因此使用 Boost.SmartPointer 的 是一个好主意enable_shared_from_this。当一个类继承自 时boost::enable_shared_from_this,它提供一个返回有效实例的shared_from_this()成员函数。shared_ptrthis

class my_class: public boost::enable_shared_from_this< my_class >
{
  void read()
  {
     boost::asio::async_read( stream, buffer, 
       boost::bind( &my_class::read_handler, shared_from_this(), 
          boost::asio::placeholders::error
          boost::asio::placeholders::bytes_transferred ) );
  }
};

boost::shared_ptr< my_class > foo( new my_class() );
foo->read();

在这个片段中,foo.get()两者foo->shared_from_this()都指向同一个实例。这有助于防止难以定位的内存泄漏。例如,在原始示例代码中,在尝试调用时Protocol::AsyncReadMessageif的复制构造函数抛出了内存泄漏。Boost.Asio 的异步 TCP 日间服务器和许多示例都显示在 Boost.Asio 中使用。为了更深入地理解,这个问题专门涵盖了异步 Boost.Asio 函数和.AsyncReadHandlerAsyncReadMessageenable_shared_from_thisshared_ptr


此外,在原始代码中,创建Protocol::AsyncHelper模板类可能比让它成为具有模板成员函数的非模板类更容易。这将允许AsyncHelper接受协议、流和处理程序作为构造函数参数,并将它们存储为成员变量。此外,它使bind调用更易于阅读,因为它减少了需要传递的参数数量,并且由于成员函数不再是模板,因此无需指定它们的完整类型。 是一个示例的快速传递。

于 2012-07-25T22:10:12.317 回答