java - 从 Jni 调用的 C++ 析构函数上的段错误

标签 java c++ pointers java-native-interface

我正在进行一个研究项目,以构建一个提供图像处理工具的库。我需要将它从 C++ 包装到其他语言。

我目前正在使用 Jni(Java native 接口(interface))进行 Java 实现。

我的 C++ 核心是用单例模式构建的。 Java 调用 C++ 以获取指向单例的指针。

static Kernel *getInstance()
    {
        if (!m_kernel)
            m_kernel = new Kernel;
        return m_kernel;
    }

C++ 将指针作为 long 值返回。

    JNIEXPORT jlong JNICALL Java_JavaCore_openKernelInstance(JNIEnv *, jobject)
{
    Kernel* kernel=Kernel::getInstance();
    std::cout << "pointer value at open" << kernel << std::endl;
    return long(kernel);
}

Java 在每个需要访问这个对象的方法中都提供了这个值,以告诉 C++ 这个对象所在的位置(它不再持有指针)。

结果

pointer address hex 10x7f0a440e3a20
pointer adress dec 139682068183584
id session1=0
id session2=1

除“ session ”结束外,一切正常。当 Java 要求 C++ 关闭其工作并删除其对象时,会发生以下情况

pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
pointer delete0x7f9aa40d3660
Segmentation fault (core dumped)

有一个无限循环,它试图删除指针。这是析构函数

Kernel::~Kernel(){
std::cout << "pointer delete" << m_kernel << std::endl;
delete m_kernel;

java代码

public static void main(String[] args){
    JavaCore jc = new JavaCore();
    long l = jc.openKernelInstance();
    int idSession = jc.openSession(l);
    int idSession2 = jc.openSession(l);
    System.out.println("pointer dec="+l);
    System.out.println("id session1="+idSession);
    System.out.println("id session2="+idSession2);
    jc.closeKernelInstance(l);
}

最佳答案

发生这种情况是因为您在析构函数中递归地删除了 m_kernel 对象。每次调用 delete m_kernel 时,您都会调用同一个析构函数。你不应该在析构函数中删除 m_kernel,在对象上调用一次 delete 就足够了:像这样。

void closeKernelInstance() {
    delete m_kernel;
}

在这种情况下析构函数应该是空的:

Kernel::~Kernel(){
}    

顺便说一句,你可以考虑使用迈耶的单例,在这种情况下你的单例将在退出时自动销毁:

static Kernel & getInstance()
{
    static Kernel theInstance;
    return theInstance;
}

关于java - 从 Jni 调用的 C++ 析构函数上的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29796933/

相关文章:

c++ - 使用 malloc 与 new

java - Java Swing 中的错误的publish()/process()交互

Java 扫描器分隔符检测到 ';',但未检测到 '\n'

C++ 泛型编程的精妙之处

C++ 在另一个目录中打开 .txt 文件

c++ - cpp 中 Graph 的最简单实现

c++ - 我不明白数组名称是如何指向数组的指针

java - Eclipse插件,自定义运行命令

java - Android butterknife

c - 将字符串指针传递给 lua