【问题标题】:boost asio set_verify_callback leaks shared_ptrboost asio set_verify_callback 泄漏 shared_ptr
【发布时间】:2014-11-20 07:31:28
【问题描述】:

在 ssl 套接字上使用 set_verify_callback 时出现泄漏。我有一个类“CClientSock”,成员为“boost::asio::ssl::stream m_socket;”

我的 CClientSock 类派生自 'enable_shared_from_this

类 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 实例将被正确销毁。

代码如下所示:

无效 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(), 端点迭代器, boost::bind(&CClientSock::handle_connect, shared_from_this(), boost::asio::placeholders::error)); } bool CClientSock::verify_certificate( 布尔预验证, boost::asio::ssl::verify_context& ctx ) { 字符主题名称[256]; X509* 证书 = X509_STORE_CTX_get_current_cert(ctx.native_handle()); X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); 系统时间 st; GetLocalTime(&st); CString s; s.Format("%02d SSL 验证:%s", m_nId, subject_name); LogMsg(m_dwThreadId, &st, s, 0, NULL); 返回预验证; }

在“set_verify_callback”中是否需要做一些事情来释放引用?

【问题讨论】:

    标签: c++ sockets boost memory-leaks boost-asio


    【解决方案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 );
        }
    });
    

    【讨论】:

    • 感谢 Sam - 我试过了,但无法使用各种捕获模式([]、[&]、[=])对其进行编译。我看到各种形式的:“错误 C3493:‘弱’不能被隐式捕获,因为没有指定默认捕获模式”。我对 lambdas 不太熟悉,因此可能还有其他可用选项。有什么我想念的吗?
    • @Ken 需要在 lambda 中显式捕获 weak_ptr,答案已更新
    【解决方案2】:

    在 sehe 和 Sam Miller 的回复后,我得到了这个工作。我最终使用了 Sam 显示的大部分代码,使用了 sehe 首次发布的“共享指针循环”的想法。

    我修改了 lambda 表达式以使用“按值”捕获子句 ([=])。这告诉编译器如何处理weak_ptr 变量。然后我修改了返回布尔值的函数的表达式。我最终得到了这个,它确实允许销毁对象实例。

    boost::weak_ptr 弱(shared_from_this()); m_socket.set_verify_callback([=](bool p, boost::asio::ssl::verify_context& context)->bool { boost::shared_ptr 强(弱); 如果(强){ p = strong->verify_certificate(p, context); } 返回 p; });

    【讨论】:

      【解决方案3】:

      我有一种预感,SSL 上下文可能会被重复使用。

      在这种情况下,您可以显式管理上下文,以便知道它何时被销毁:

      或者,可能存在由持有套接字的上下文创建的共享指针循环,因此没有任何上下文或处理程序被释放。 (在这种情况下,您应该会看到更多问题)。尝试通过显式释放处理程序来打破循环:

      s.set_verify_callback([](bool p, verify_context&) { return p; });
      

      【讨论】:

      • 谢谢-但我不完全理解如何使用您的示例。您能否在我的示例中说明如何实现?
      • 不过,你必须要有耐心,因为我将在晚上剩下的时间里工作:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-22
      • 1970-01-01
      • 2013-03-18
      • 2011-06-19
      • 2015-12-16
      相关资源
      最近更新 更多