我正在使用Boost.Beast和Boost.Asio开发一个C++多线程WebSocket客户端。我偶尔会在WebSocket握手过程(do_handshake方法)中遇到分段错误(EXC_BAD_ACCESS)。该应用程序旨在处理来自服务器的实时数据流。
下面是我的WebSocketClient类的简化版本:
class WebSocketClient
{
private:
OrderBook &orderBook_;
string coin_;
boost::asio::io_context ioc_;
tcp::resolver resolver_;
ssl::context ssl_context_;
websocket::stream<boost::asio::ssl::stream<tcp::socket>> ws_;
public:
WebSocketClient(OrderBook &orderBook, const string &coin)
: orderBook_(orderBook),
coin_(coin),
resolver_(ioc_),
ssl_context_(ssl::context::tlsv12_client),
ws_(ioc_, ssl_context_)
{
ssl_context_.set_default_verify_paths();
ws_.next_layer().set_verify_mode(ssl::verify_peer);
ws_.next_layer().set_verify_callback(ssl::rfc2818_verification("stream.binance.com"));
}
void connectAndSubscribe()
{
try
{
cout << "&ws_ = " << &ws_ << endl;
// Resolve the host name and connect to the server
auto const results = resolver_.resolve("stream.binance.com", "9443");
auto ep = boost::asio::connect(ws_.next_layer().next_layer(), results);
string host_ = "stream.binance.com:" + to_string(ep.port());
ws_.next_layer().handshake(ssl::stream_base::client);
// Set a decorator to change the User-Agent of the handshake
ws_.set_option(websocket::stream_base::decorator(
[](websocket::request_type &req)
{
req.set(boost::beast::http::field::user_agent,
string(BOOST_BEAST_VERSION_STRING) + " websocket-client");
}));
string path = "/ws/" + coin_ + "@depth5@100ms";
ws_.handshake(host_, path);
cout << "Handshake successful." << endl;
string msg = "{\"method\": \"SUBSCRIBE\", \"params\": [\"" + coin_ + "@depth5@100ms\"], \"id\": 1}";
send(msg);
cout << "Subscription request done!" << endl;
}
catch (const std::exception &e)
{
cout << "Error in connectAndSubscribe: " << e.what() << endl;
throw; // Rethrow to be caught by the caller
}
}
字符串
该类用于多线程上下文中,其中每个线程创建一个WebSocketClient示例来处理其连接。崩溃偶尔发生,堆栈跟踪指向do_handshake方法。
我已经检查了对象的生存期,像ssl_context_、resolver_和ws_这样的对象是WebSocketClient类的成员。我确保OrderBook对象的生存期超过WebSocketClient示例。
lldb终端:
* thread #5, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010003a28b adabtc`void boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor> >, true>::do_handshake<void (*)(boost::beast::http::message<true, boost::beast::http::empty_body, boost::beast::http::basic_fields<std::__1::allocator<char> > >&)>(boost::beast::http::message<false, boost::beast::http::basic_string_body<char, std::__1::char_traits<char>, std::__1::allocator<char> >, boost::beast::http::basic_fields<std::__1::allocator<char> > >*, boost::core::basic_string_view<char>, boost::core::basic_string_view<char>, void (* const&)(boost::beast::http::message<true, boost::beast::http::empty_body, boost::beast::http::basic_fields<std::__1::allocator<char> > >&), boost::system::error_code&) + 843
adabtc`boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor> >, true>::do_handshake<void (*)(boost::beast::http::message<true, boost::beast::http::empty_body, boost::beast::http::basic_fields<std::__1::allocator<char> > >&)>:
-> 0x10003a28b <+843>: vmovaps 0x40(%rax), %ymm0
0x10003a290 <+848>: leaq 0x2210(%rsp), %rax
0x10003a298 <+856>: vmovups %ymm0, (%rax)
0x10003a29c <+860>: movq %r13, %r12
Target 0: (adabtc) stopped.
型
1条答案
按热度按时间zzoitvuj1#
这不是一个C++异常。这是一般的保护错误。你的工作不是处理它们,而是避免它们。很明显,你有UB,很可能是数据竞争。修复它,或者发布一个自包含的例子,以便我们可以审查。这是我从你的代码开始-这是我现在所有的20分钟:
Live On Coliru
字符串
在我的机器上打印出预期的
型
该应用程序旨在处理来自服务器的实时数据流
我非常怀疑它,因为我希望线程感知和异步IO。
请扩展最小的自包含代码来重现您的错误。或者简单地展示如何组织阅读以及如何在订单簿上完成线程同步。