我正在使用 boost::asio。我写了一个类负责从套接字异步读取。 在我的应用程序中,io_service 可以在一个应用程序运行期间多次停止和启动。 所以我不得不担心服务停止时的内存泄漏。 我得出了两个解决方案:
请求异步请求的类为函数提供了用于 asio 读取的缓冲区,并负责释放缓冲区。这是一个显而易见的解决方案,但我不喜欢它。将不需要的参数传递给函数看起来真的很奇怪。
绑定(bind)到回调的智能指针。这里的例子: http://pastebin.com/p8nQ5NFi
现在我正在使用第二种解决方案,但不管我怎么想,我正在发明一个轮子。异步调用中缓冲区清理的常见做法是什么?我的方法有什么隐患吗?
最佳答案
shared_ptr
方法相当普遍。然而,而不是通过 shared_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 ) );
通常,因为实例将通过 shared_ptr
进行管理, 可能在也可能不在 this
的上下文中, 使用 Boost.SmartPointer 的 enable_shared_from_this
是个好主意.当一个类继承自 boost::enable_shared_from_this
, 它提供了一个 shared_from_this()
返回有效 shared_ptr
的成员函数实例到 this
.
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::AsyncReadMessage
。如果AsyncReadHandler
的复制构造函数在尝试调用时抛出 AsyncReadMessage
. Boost.Asio 的 asynchronous TCP daytime server和许多 examples显示 enable_shared_from_this
在 Boost.Asio 中使用。为了更深入的了解,this问题具体涉及异步 Boost.Asio 函数和 shared_ptr
.
此外,在原始代码中,可能更容易制作Protocol::AsyncHelper
。一个模板类,而不是让它成为一个具有模板成员函数的非模板类。这将允许 AsyncHelper
接受协议(protocol)、流和处理程序作为构造函数参数,并将它们存储为成员变量。此外,它使 bind
调用稍微更容易阅读,因为它减少了需要传递的参数数量,并且由于成员函数不再是模板,因此无需指定它们的完整类型。 Here是一个示例的快速传递。
关于C++异步调用最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11641620/