我正在研究一个研究项目,以建立一个提供图像处理工具的图书馆。我需要它从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
除了&#34; session&#34;结束之外,一切正常。当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);
}
答案 0 :(得分:4)
这是因为您在析构函数中递归删除了m_kernel
对象。每次调用delete m_kernel
时,都会调用相同的析构函数。你不应该在析构函数中删除m_kernel
,它足以在对象上调用delete
一次:就像这样。
void closeKernelInstance() {
delete m_kernel;
}
在这种情况下,析构函数应为空:
Kernel::~Kernel(){
}
顺便说一句,您可以考虑使用Meyer的单身人士,在这种情况下,您的单身人士将在退出时自动销毁:
static Kernel & getInstance()
{
static Kernel theInstance;
return theInstance;
}