我有一个已经完成握手的boost::asio::ssl::stream<boost::asio::ip::tcp::socket。我开始异步读取,然后删除对象(销毁对象并将其内存重置为0xff)。然后,出现段错误,因为Boost Asio正在访问刚删除的对象中的内容。当我仅用boost::asio::ip::tcp::socket测试时,我的回调仅在操作中止的情况下调用,这是我在使用ssl::stream时所期望的。

我用来重现该问题的代码:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

template <typename T>
void debug(T& a)
{
    for (unsigned int i = 0; i < sizeof(a); ++i)
    {
        if (i % 8 == 0) std::cout << std::endl << i << "\t";
        std::cout << unsigned(reinterpret_cast<unsigned char*>(&a)[i]) << " ";
    }
    std::cout << std::endl;
}

template <typename T>
void destruct(T& a)
{
    a.~T();
    memset(&a, 0xff, sizeof(a));
}

int main()
{
    char buffer[4096];
    const char* write = "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n";

    boost::asio::io_service io;
    //boost::asio::ip::tcp::socket* socket = new boost::asio::ip::tcp::socket(io);
    boost::asio::ssl::context ssl_context(boost::asio::ssl::context::tlsv1);

    boost::asio::ssl::stream<boost::asio::ip::tcp::socket>* socket = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(io, ssl_context);
    socket->set_verify_mode(boost::asio::ssl::verify_none);

    boost::asio::ip::tcp::resolver resolver(io);
    boost::asio::ip::tcp::resolver::query query("stackoverflow.com", std::to_string(443));

    resolver.async_resolve(query, [&](const boost::system::error_code& ec, boost::asio::ip::tcp::resolver::iterator result)
    {
        if (ec) throw ec;

        //socket->async_connect(*result, [&](const boost::system::error_code& ec)
        socket->next_layer().async_connect(*result, [&](const boost::system::error_code& ec)
        {
            if (ec) throw ec;

            socket->async_handshake(boost::asio::ssl::stream_base::client, [&](const boost::system::error_code& ec)
            {
                if (ec) throw ec;

                boost::asio::async_write(*socket, boost::asio::buffer(write, std::string(write).size()), [&](const boost::system::error_code& ec, std::size_t)
                {
                    if (ec) throw ec;


                    socket->async_read_some(boost::asio::buffer(buffer, 4096), [&](const boost::system::error_code& ec, std::size_t len)
                    {
                        if (ec) {
                            std::cout << ec.message() << std::endl;
                            debug(*socket);
                            return;
                        }

                        std::cout.write(buffer, len);

                        std::cout << std::endl << "End" << std::endl;
                    });

                    debug(*socket);
                    destruct(*socket);
                });

            }
            );
        });
    });

    io.run();

    debug(*socket);
}

最佳答案

实际上,您不是:


通常的方法是使您的 session (“连接”)成为boost::enable_shared_from_this派生的类,并将完成处理程序绑定(bind)到shared_from_this()。这样,您可以让shared_ptr<Session>超出范围,并且仅在最后一个挂起的操作完成(包括完成处理程序)后,才删除该对象。
奖励
这是等效的代码,没有“false”异步,具有自动生存期和隐式异常!
Live On Coliru

#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

namespace ba  = boost::asio;
namespace ssl = ba::ssl;
using ba::ip::tcp;

int main()
{
    char buffer[4096];
    const char* write = "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n";

    ba::io_service io;
    ssl::context ssl_context(ssl::context::tlsv1);
    ssl::stream<tcp::socket> socket(io, ssl_context);

    socket.set_verify_mode(ssl::verify_none);

    tcp::resolver resolver(io);
    tcp::resolver::query query("stackoverflow.com", std::to_string(443));

    auto result = resolver.resolve(query);
    socket.next_layer().connect(*result);

    socket.handshake(ssl::stream_base::client);

    /*size_t ignore = */ba::write(socket, ba::buffer(write, std::string(write).size()));

    boost::system::error_code ec;
    size_t len = socket.read_some(ba::buffer(buffer, 4096), ec);
    if (ec) {
        std::cout << ec.message() << "\n";
    } else {
        std::cout.write(buffer, len);
    }

    std::cout << "\nEnd\n";
}

关于c++ - 如果ssl::stream <tcp::socket>具有待处理的操作,是否可以删除它?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32260702/

10-09 20:28
查看更多