android - C++ 库导致原生 Android 崩溃
问题描述
我正在学习如何将 C++ 项目实现到原生 Android 中,并发现自己需要导入一个 C++ 库。一切都很好,但问题是当onBackPressed()
被调用时,用户会按预期定向到上一个片段,但是当他们重新进入由 C++ 库填充的 Activity 时,会发生崩溃。
我得到的唯一错误是A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8 in tid 9408 (GLThread 27055), pid 9296 (fluidSimulation)
我开始在文件中进行一些挖掘,在该gl_code.cpp
文件中我将值传递给暴露的 C++ 方法,我相信我已经确定了这个问题,但我被困在一个修复中......
每次创建 Activity 时都会调用以下 C++ 方法:
//This is global as it is used in other methods
void *fluid;
extern "C" JNIEXPORT void JNICALL
Java_com_android_ui_fluidSimulation_FluidLib_init(JNIEnv *env, jobject obj, jint width,
jint height) {
fluid = fluidCreate((int) width, (int) height);
}
现在,我发现在调用fluid
活动退出后,指针被保存在内存中onBackPressed()
。我已经弄清楚每次活动开始时都需要调用此方法,但我需要了解如何重置指针。
我delete fluid;
在打电话之前尝试过fluidCreate
,但这不起作用。有没有办法解决这个问题,还是我受图书馆的摆布,最好放弃它?
更新 1
所以,每一帧都会调用下面的方法,我注意到当流体添加到帧时会发生崩溃。
static double now_ms(void) {
struct timespec res;
clock_gettime(CLOCK_REALTIME, &res);
return 1000.0 * res.tv_sec + (double) res.tv_nsec / 1e6;
}
extern "C" JNIEXPORT void JNICALL
Java_com_android_ui_fluidSimulation_FluidLib_step(JNIEnv *env, jobject obj) {
double t = now_ms();
//Below is printed
__android_log_write(ANDROID_LOG_ERROR, "Tag", "Gets before fluidOnFrame");
fluidOnFrame(fluid, t);
//Below is is not printed
__android_log_write(ANDROID_LOG_ERROR, "Tag", "Gets after fluidOnFrame");
}
这些方法在 Native Android 中调用如下:
private class Renderer : GLSurfaceView.Renderer {
override fun onDrawFrame(gl: GL10) {
FluidLib.step()
}
override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
FluidLib.init(width, height)
}
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
// Do nothing.
}
}
使用的方法定义如下:
object FluidLib {
/**
* @param width the current view width
* @param height the current view height
*/
external fun init(width: Int, height: Int)
external fun destroy()
external fun step()
init {
System.loadLibrary("gl_code")
}
}
我与 C++ 库交互的文件:
/**
* C-Style API to enable the fluid component to be used with C-based clients (i.e. Swift)
*/
#ifndef Fluid_h
#define Fluid_h
enum PointerType {
MOUSE = 0,
TOUCH = 1,
PEN = 2
};
#ifdef __cplusplus
extern "C" {
#endif
void* fluidCreate(int width, int height);
void fluidOnFrame(void* fluidPtr, double frameTime_ms);
#ifdef __cplusplus
}
#endif
#endif /* Fluid_h */
更新 2
为了更好地理解问题的原因,我最终在我的fluidCreate
方法周围创建了一个 if 语句,以查看它是指针还是其他问题,如下所示:
void *fluid;
void *newFluid;
extern "C" JNIEXPORT void JNICALL
Java_com_android_ui_fluidSimulation_FluidLib_init(JNIEnv *env, jobject obj, jint width,
jint height) {
if(fluid == 0) {
fluid = fluidCreate((int) width, (int) height);
}else{
newFluid = fluidCreate((int) width, (int) height);
}
}
然后对我的称为每一帧的方法执行以下操作:
extern "C" JNIEXPORT void JNICALL
Java_com_android_ui_fluidSimulation_FluidLib_step(JNIEnv *env, jobject obj) {
double t = now_ms();
if(newFluid == 0) {
__android_log_write(ANDROID_LOG_ERROR, "Tag", "Original Fluid on Frame");
fluidOnFrame(fluid, t);
}else{
__android_log_write(ANDROID_LOG_ERROR, "Tag", "New Fluid on Frame");
fluidOnFrame(newFluid, t);
}
}
现在,即使使用了不同的指针,仍然会导致崩溃,这让我觉得 C++ 库方法中似乎有一个错误fluidOnFrame
......
解决方案
我认为你的方向是正确的。崩溃日志对我来说也像是内存异常,我认为内存没有正确释放。
fluid
退出活动时需要销毁指针。我想建议编写另一个函数,如下所示。
extern "C" JNIEXPORT void JNICALL
Java_com_android_ui_fluidSimulation_FluidLib_destroy(JNIEnv *env) {
delete fluid;
}
并在您Activity
的onPause
or函数中调用此onDestroy
函数。
我希望这会破坏内存引用并避免Fatal signal 11 (SIGSEGV)
您遇到的崩溃问题。
推荐阅读
- r - r 将逻辑矩阵列表应用于矩阵列表
- java - Spring Boot 2.1 中的 DataSource bean 覆盖
- ios - 如何使用 EasyPeasy 使 UITableViewCell 可调整大小?
- php - PHP - 如何避免在 Web 浏览器中使用我的脚本
- node.js - pm2日志实时输出
- html - 超链接图像容器太宽
- javascript - 复制 URL 参数并粘贴到 HTML
- flutter - Flutter 异步表单验证
- python - 如何在 Mac OS X 上为 python av 安装 h264 编解码器
- javascript - 只有在 ie11 上打开开发工具时才可以解决 photoeditorSDK 的问题?