Android C ++:加载的共享库中未捕获的异常

时间:2018-11-14 09:52:04

标签: android c++ android-ndk shared-libraries dlopen

我是stackoverflow的新手,我希望在Android C ++上寻求帮助。

我正在尝试用C ++实现一个非常简单的Android测试程序,该程序也调用以C ++实现的已加载共享库中的函数。

这是我主要的JNI实现(native-lib.cpp

#include <jni.h>
#include <string>
#include <dlfcn.h>
#include "external.hpp"

extern "C" JNIEXPORT jstring JNICALL
Java_com_useless_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    void* handle;
    void (*funcext)();
    handle = dlopen("libexternal.so",RTLD_LAZY);
    funcext = (void (*)(void))dlsym(handle, "_Z5func2v");
    try {
        funcext();
    }
    catch (MyException &err)
    {
        std::string hello = "MyException from C++";
        return env->NewStringUTF(hello.c_str());
    }
    catch (GenericException &err)
    {
        std::string hello = "GenericException from C++";
        return env->NewStringUTF(hello.c_str());
    }
    catch (GenericException* err)
    {
        std::string hello = "GenericException* from C++";
        return env->NewStringUTF(hello.c_str());
    }

    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

这是我的libexternal.so实现(external.cpp):

#include <jni.h>
#include <string.h>
#include "external.hpp"
GenericException::GenericException(){};
GenericException::GenericException(int errcode,char* msg)
{
        errorcode = errcode;
        memset(message,0,256);
        strcpy(message,msg);
}

MyException::MyException(int errcode,char* msg)
{
    errorcode = errcode;
    memset(message,0,256);
    strcpy(message,msg);
}

void func()
{
    throw MyException(10,"Error1!");
}
bool func3()
{
    try {
        func();
    }
    catch (GenericException &err)
    {
        return false;
    }
    return true;
}

void func2()
{
    if (!func3())
        throw MyException(11,"Error2!");
}

external.hpp文件的定义如下:

void func();
void func2();
bool func3();
class GenericException
{
    public:
    GenericException();
    GenericException(int errcode,char* msg);
    protected:
    int errorcode;
    char message[256];
};

class MyException : public GenericException
{
    public:
    MyException(int errcode,char* msg);
};

程序编译并链接干净,但是当我运行它时, logcat 中的以下消息使android应用程序崩溃:

2018-11-14 09:57:42.058 6519-6519/com.useless.myapplication A/libc: /usr/local/google/buildbot/src/android/ndk-release-r18/external/libcxx/../../external/libcxxabi/src/abort_message.cpp:73: abort_message: assertion "terminating with uncaught exception of type MyException" failed

当我尝试执行external.cpp第41行时,错误会上升:

throw MyException(11,"Error2!");

正如其他帖子所建议的那样,我发现我尝试在我的应用-frtti cppflgs中启用build.gradle标志,但这不能解决错误。

我已经尝试在 Linux MacOS 上运行相同的代码(实际上没有Java顶层),但是在这些平台上,{{ 1}}代码。

关于Android中的C ++异常,我是否不了解? 如何在Android上捕获由 dlopen 加载的库引发的异常?

谢谢

1 个答案:

答案 0 :(得分:0)

您的异常类型没有键功能,因此它的typeinfo与vague linkage一起发出。这意味着它在使用它的每个库中都是一个弱符号。

您的JNI库加载并解析其自己的typeinfo。然后加载了倾斜的库,并且解析了它自己的typeinfo,因为它无法访问父作用域(System.loadLibrary使用RTLD_LOCAL)。因此,对于您的异常类型,有两个单独的typeinfo对象。通过比较typeinfo对象的地址来检查RTTI的相等性(请参见C++ ABI spec)。

我不确定在不将JNI代码直接链接到libexternal.so的情况下是否可以解决该问题。如果您添加了完成这项工作所需的关键功能(将在libexternal.so中定义),那么我相信您需要链接至该功能才能链接JNI代码。