我在Android应用程序中使用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;
}
最佳答案
崩溃不是随机的。
尤其是如果它们来自未捕获的异常(那么,它们来自于处理异常的失败)就不会。
通常情况下,异常可以很好地说明问题所在。在您的情况下:
boost::system::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 not very informative but I add it here:
没有提供信息。这是很长一段时间以来我看到的最容易被滥用的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 });
}
虽然,实际上,最好只使用值(value)语义: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>
。示范代码
Live On Coliru
#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>
"
关于android - Android应用程序内部boost中未捕获的boost::wrapexcept <boost::system::system_error>类型的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62662278/