在ssl套接字上使用set_verify_callback时,我发现了泄漏。我有一个“CClientSock”类,其成员为“boost :: asio :: ssl :: stream m_socket;”
我的CClientSock类派生自'enable_shared_from_this
class CClientSock : public boost::enable_shared_from_this
如果我打电话:
m_socket.set_verify_callback( boost::bind(&CClientSock::verify_certificate, shared_from_this(), _1, _2));
然后我的CClientSock实例永远不会被破坏。
如果我没有调用“m_socket.set_verify_callback”,那么我的CClientSock实例会被正确销毁。
代码如下所示:
void CClientSock::StartPoll() { m_socket.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert); m_socket.set_verify_callback( boost::bind(&CClientSock::verify_certificate, shared_from_this(), _1, _2)); boost::asio::ip::tcp::resolver::iterator endpoint_iterator; endpoint_iterator = ResolveAddress("xxx.xxx.xxx.xxx", nPort); boost::asio::async_connect( m_socket.lowest_layer(), endpoint_iterator, boost::bind(&CClientSock::handle_connect, shared_from_this(), boost::asio::placeholders::error)); } bool CClientSock::verify_certificate( bool preverified, boost::asio::ssl::verify_context& ctx ) { char subject_name[256]; X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle()); X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); SYSTEMTIME st; GetLocalTime(&st); CString s; s.Format("%02d SSL Verify: %s", m_nId, subject_name); LogMsg(m_dwThreadId, &st, s, 0, NULL); return preverified; }
是否有必要在“set_verify_callback”中完成某项内容以释放引用?
答案 0 :(得分:1)
通过在验证回调中保留shared_ptr<CClientSock>
,您有一个周期性参考。上下文维护一个boost::asio::ssl::detail::verify_callback
成员,其中包含您的共享指针。要打破循环,请使用带有lambda
std::weak_ptr<CClientSock> weak( shared_from_this() );
m_socket.set_verify_callback([weak](bool p, boost::asio::ssl::verify_context& context) {
std::shared_ptr<CClientSock> strong( weak );
if ( strong ) {
strong->verify_certificate( p, context );
}
});
答案 1 :(得分:1)
在sehe和Sam Miller的回应之后,我得到了这个。我最终使用了Sam显示的大部分代码,使用了共享指针循环&#39;想法首先由sehe发布。
我修改了lambda表达式以使用&#39; by value&#39;捕获子句([=])。这告诉编译器如何处理weak_ptr变量。然后我修改了返回布尔值的函数的表达式。我最终得到了这个,它允许对象实例被销毁。
boost::weak_ptr weak( shared_from_this() ); m_socket.set_verify_callback([=](bool p, boost::asio::ssl::verify_context& context)->bool { boost::shared_ptr strong(weak); if ( strong ) { p = strong->verify_certificate(p, context); } return p; });
答案 2 :(得分:0)
我预感到SSL上下文可能会被重用。
在这种情况下,您可以明确地管理上下文,以便知道它何时被销毁:
或者,可能存在由保持套接字的上下文创建的共享指针循环,以便不释放上下文或处理程序。 (在这种情况下,您应该看到更多问题)。尝试通过显式释放处理程序来打破循环:
s.set_verify_callback([](bool p, verify_context&) { return p; });