我有一个已经完成握手的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/