我正在使用 boost::asio。我写了一个负责从套接字异步读取的类。
在我的应用程序中,io_service 可以在一个应用程序运行期间多次停止和启动。
所以我不得不担心服务停止时的内存泄漏。
我想到了两个解决方案:
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 显示在 Boost.Asio 中使用的 enable_shared_from_this
。为了更深入的理解,this 问题专门涵盖了异步 Boost.Asio 函数和 shared_ptr
。此外,在原始代码中,将
Protocol::AsyncHelper
设为模板类可能更容易,而不是将其设为具有模板成员函数的非模板化类。这将允许 AsyncHelper
接受协议(protocol)、流和处理程序作为构造函数参数,将它们存储为成员变量。此外,它使 bind
调用更容易阅读,因为它减少了需要传递的参数数量,并且由于成员函数不再是模板,因此无需指定它们的完整类型。 Here 是一个例子的快速传递。关于C++ 异步调用最佳实践,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11641620/