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

标签 android c++ boost java-native-interface sigabrt

我在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/

相关文章:

android studio - 手动下载模拟器的系统镜像

c++ - SFINAE 用于回调注册

c++ - 是否应该捕获 boost::asio::io_service::run() 抛出的异常?

c++ - 基于类模板参数专门化 C++ 成员函数

c++ - SWIG, boost 共享指针和继承

java - 在相对布局中动态移动 View

java - 切换 Activity 时崩溃

Android数据存储性能

c++ - 为什么 Microsoft 有 IHTMLDocument、IHTMLDocument2、...、IHTMLDocument8?

c++ - 如何使用 decltype 获取某些类类型的成员函数的地址?