android - C++库导致 native Android崩溃

标签 android c++ java-native-interface

我正在学习如何在本地Android中实现C++项目,并发现自己要导入一个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时, Activity 退出后,onBackPressed()指针仍保留在内存中。我已经得出结论,每次 Activity 开始时都需要调用此方法,但是我需要了解如何重置指针。

我在调用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方法中似乎存在一个错误...

最佳答案

我认为您的方向正确。崩溃日志在我看来也像是内存异常,我认为内存没有正确释放。

退出 Activity 时,必须销毁fluid指针。我建议您编写如下的另一个函数。

extern "C" JNIEXPORT void JNICALL
Java_com_android_ui_fluidSimulation_FluidLib_destroy(JNIEnv *env) {
    delete fluid;
}

并在ActivityonPauseonDestroy函数中调用此函数。

我希望这将破坏内存引用,并避免出现Fatal signal 11 (SIGSEGV)崩溃的问题。

关于android - C++库导致 native Android崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60606661/

相关文章:

c++ - 在 C++ 中为结构实现索引器

java - 使用 jna.jar 和 platform.jar 出现 NoClassDefFoundError

java - Spring 启动 : Is there a similar way to hold an XML resource of strings and reference them like in Androids framework?

java - 如何通过ListAdpter显示多张图片?

javascript - 跨平台移动浏览器中可滚动 div 中的滚动条

java - Android ArrayIndexOutOfBoundsException 向 mysql 插入行

c++ - 递归方法 C++

C++ mktime 更改我的 tm_struct 的值

java - 如何在 Mac OS X 中使用带有 Java 的 Windows DLL?

java - 如何从java调用c++目标文件中的函数?