来自 Android 应用程序内部的 boost 类型的 boost::wrapexcept<boost::system::system_error> 的未捕获异常

Uncaught exception of type boost::wrapexcept<boost::system::system_error> from boost inside Android app

本文关键字:boost system error gt 捕获异常 wrapexcept 应用程序 Android 内部 类型 来自      更新时间:2023-10-16

我正在使用boost inide一个安卓应用程序并获得一个随机的SIGABRT:

"terminating with uncaught exception of type boost::wrapexcept<boost::system::system_error>: partial message" failed'
2020-06-30 17:44:52.643 24683-24683/? A/DEBUG:     eax 00000000  ebx 0000600f  ecx 00006057  edx 00000006
2020-06-30 17:44:52.643 24683-24683/? A/DEBUG:     esi 85c46978  edi 85c46920
2020-06-30 17:44:52.643 24683-24683/? A/DEBUG:     xcs 00000073  xds 0000007b  xes 0000007b  xfs 0000003b  xss 0000007b
2020-06-30 17:44:52.643 24683-24683/? A/DEBUG:     eip aa5d1424  ebp 85c42918  esp 85c428bc  flags 00000296
2020-06-30 17:44:52.644 24683-24683/? A/DEBUG: backtrace:
2020-06-30 17:44:52.644 24683-24683/? A/DEBUG:     #00 pc ffffe424  [vdso:aa5d1000] (__kernel_vsyscall+16)
2020-06-30 17:44:52.644 24683-24683/? A/DEBUG:     #01 pc 0007a03c  /system/lib/libc.so (tgkill+28)
2020-06-30 17:44:52.644 24683-24683/? A/DEBUG:     #02 pc 00075885  /system/lib/libc.so (pthread_kill+85)
2020-06-30 17:44:52.644 24683-24683/? A/DEBUG:     #03 pc 0002785a  /system/lib/libc.so (raise+42)
2020-06-30 17:44:52.645 24683-24683/? A/DEBUG:     #04 pc 0001ee36  /system/lib/libc.so (abort+86)
2020-06-30 17:44:52.645 24683-24683/? A/DEBUG:     #05 pc 00023d48  /system/lib/libc.so (__libc_fatal+40)
2020-06-30 17:44:52.645 24683-24683/? A/DEBUG:     #06 pc 0001f300  /system/lib/libc.so (__assert2+64)

我正在运行Android模拟器,所以这发生在X86 cpu上,但我不能说更多, ASM对我来说真的很晦涩。代码似乎并不复杂。 这是从 JNI 调用的 CPP 文件:

HttpClient syncclient(io_service);
syncclient.getJsonSync();   <---SIGABRT

getJsonSync 这样做:

getJsonSync(){
tcp::resolver resolver(io_service);
beast::tcp_stream stream(io_service);
auto const results = resolver.resolve(server, port);
stream.connect(results);
http::request<http::string_body> req{http::verb::post, path, 11};
req.set(http::field::host, server);
req.version(11);
req.set(http::field::authorization, authorization);
req.set(beast::http::field::content_type, "application/json");
req.set(beast::http::field::connection, "close");
req.body() = data;
req.prepare_payload();
http::write(stream, req);
beast::flat_buffer buffer;
http::response<http::dynamic_body> res;
http::read(stream, buffer, res);
Response *nr = NULL; //structure where msg body and http status code are copied
if (res.result_int() == 200*){
std::string body { boost::asio::buffers_begin(res.body().data()),
boost::asio::buffers_end(res.body().data()) };
initNativeResponse(&nr, id); //alloc the structure
if(nr == NULL){
/* memory allocation failed */
return NULL;
}
nr->obj = strdup(body.c_str());
nr->msg_code =res.result_int();
}
beast::error_code ec;
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
if (ec && ec != beast::errc::not_connected){
return NULL;
}
return nr;
}

和 initNativeResponse 信息量不是很大,但我在这里添加它:

void initNativeResponse(Response **response, int msgId){
*response = (Response *) malloc(sizeof(struct native_response));
if(*response == NULL){
return;
}
(*response)->id = msgId;
(*response)->obj = NULL;
}

崩溃不是随机的。

特别是如果它们来自未捕获的异常(那么它们来自未能处理异常(。

通常,异常可以很好地指示问题所在。在您的情况下:

提升::系统::system_error:部分消息

https://www.boost.org/doc/libs/1_66_0/libs/beast/doc/html/beast/using_websocket/send_and_receive_messages.html

那是你的问题。分析器未收到完整消息。原因有很多。如果连接在响应中途关闭,那将是很自然的。

读取代码

std::string body{ boost::asio::buffers_begin(res.body().data()),
boost::asio::buffers_end(res.body().data()) };

让我觉得你应该一开始就使用string_body

旁白

initNativeResponse 信息量不是很大,但我在这里添加它:

没有信息。这是我在很长一段时间内看到的最过时的C滥用。strdup也一样。 无论如何,strdup使它不是 POD。

这是它的 c++ 写法:

struct Response {
int id;
int msg_code;
char* obj = nullptr;
~Response() {
::free(static_cast<void*>(obj));
obj = nullptr;
}
};
using ResponsePtr = std::unique_ptr<Response>;
ResponsePtr initNativeResponse(int msgId) {
return std::make_unique<Response>(Response{ msgId, 0, nullptr });
}

虽然,实际上,你最好只使用值语义:

struct Response {
int id;
int msg_code = 0;
std::string obj;
};

现在你可以写:

return Response{id, res.result_int(), std::move(res.body())};

它将是异常安全的,更多的分配优化等。如果你真的必须指出"没有回应"(为什么?这只会在malloc失败时发生......例外区域(,使用std::optional<Response>

演示代码

住在科里鲁

#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <boost/beast/http.hpp>
#include <memory>
namespace beast = boost::beast;
namespace http = beast::http;
using boost::asio::ip::tcp;
boost::asio::io_service io_service;
auto constexpr server = "example.com";
auto constexpr port = "http";
auto constexpr path = "/";
auto constexpr authorization = "dXNlcjpwYXNzd29yZA==";
auto constexpr data = R"({ "some" : 42, "data": { "nested": [1,2,3], "fields" : null } })";
struct Response {
int id;
unsigned msg_code = 0;
std::string obj;
};
static inline auto make_request() {
http::request<http::string_body> req{ http::verb::post, path, 11 };
req.set(http::field::host, server);
req.version(11);
req.set(http::field::authorization, authorization);
req.set(beast::http::field::content_type, "application/json");
req.set(beast::http::field::connection, "close");
req.body() = data;
req.prepare_payload();
return req;
}
Response getJsonSync() {
tcp::resolver resolver(io_service);
beast::tcp_stream stream(io_service);
auto results = resolver.resolve(server, port);
stream.connect(results);
http::write(stream, make_request());
beast::flat_buffer buffer;
http::response<http::string_body> res;
http::read(stream, buffer, res);
if (res.result_int() == 200) {
stream.socket().shutdown(tcp::socket::shutdown_both); // exception handling FTW
int id = 42; // FIXME
return { id, res.result_int(), std::move(res.body()) };
}
return {};
}
#include <iostream>
#include <iomanip>
int main() {
auto res = getJsonSync();
std::cout << "res.id: " << res.id << "n";
std::cout << "res.msg_code: " << res.msg_code << "n";
std::cout << "res.obj: " << std::quoted(res.obj) << "n";
}

打印(给定网络访问权限(:

res.id: 42
res.msg_code: 200
res.obj: "<!doctype html>
<html>
[... snip ...]
</html>
"