android - Android C++:加载的共享库中未捕获的异常
问题描述
我是 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);
};
该程序编译并链接干净,但是当我运行它时,我的 android 应用程序崩溃并在logcat中显示以下消息:
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 顶层),但在这些平台上,异常被native-lib.cpp
代码捕获。
关于 Android 中的 C++ 异常,有什么我不知道的吗?我怎样才能捕捉到我在 Android上用dlopen加载的库引发的异常?
谢谢
解决方案
您的异常类型没有关键功能,因此它的 typeinfo 是通过vague links 发出的。这意味着它在每个使用它的库中都是一个弱符号。
您的 JNI 库加载并解析其自己的类型信息。然后加载您的 dlended 库并解析其自己的 typeinfo,因为它无法访问父范围(System.loadLibrary
uses RTLD_LOCAL
)。因此,您的异常类型有两个单独的 typeinfo 对象。通过比较 typeinfo 对象的地址来检查 RTTI 是否相等(请参阅C++ ABI 规范)。
我不确定是否可以在不直接将 JNI 代码链接到 libexternal.so 的情况下解决此问题。如果您添加了使这项工作所需的关键功能(将在 libexternal.so 中定义),那么我相信您需要链接到它才能链接您的 JNI 代码。
推荐阅读
- python - 如何组合和比较两个笔记本的结果
- python - Selenium 得到大于 x 的 img
- sql - 如何从一列的不同行中获取值以分隔列
- amazon-web-services - SQS 是否允许在重复数据删除期间重试事件?
- php - PHP PDO 连接在 GoDaddy 连接字符串上显示 2 个 @ 符号
- excel - Excel VBA - 从单元格读取时,代码会将小数转换为整数
- android-room - 你如何制作一个自动生成的复合主键?
- gcc - CMake 微软视觉工作室 + gcc
- php - 使用 NGINX 的多个路由位置阻止 PHP 访问
- java - 为什么这个递归方法返回 400 而不是 404?