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



我正在做一个研究项目,建立一个提供图像处理工具的库。我需要将其从C++包装为其他语言。

我目前正在使用 Jni(Java Native Interface)进行 Java 实现。

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

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

C++ 将指针作为长整型值返回。

    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

除了"会话"结束之外,一切正常。当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;

}

爪哇代码

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;
}

最新更新