boost asio set_verify_callback泄漏shared_ptr

时间:2014-09-25 13:37:12

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

在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”中完成某项内容以释放引用?

3 个答案:

答案 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; });