2016-06-23 34 views
0

我遇到了奇怪的问题。为了使事情短:我写了一个Android应用程序,利用OpenCV的两个活动:Android + OpenCV上的SIGSEGV

活性1预览前置摄像头,并在用户点击启动活性2,通过意向发送当前帧的地址

活性2受让人它是给定地址下框架的Mat克隆类型的本地字段,并允许用户对其进行简单的操作(即在HSV色彩空间中执行inRange方法)。 Mat被转换为ImageView显示在ImageView中:这发生在Activity2开始(对于原始捕获帧)以及每个用户对SeekBar的操作之后。

Activity1是Activity2的父级,因此单击后退按钮将重新启动Activity1。 现在来怪异的一部分(S):一段时间后

1)(少于1分钟)活动1崩溃,与libc: Fatal signal 11 (SIGSEGV) - 你可以想像,它不会发生在活性2是从来没有开始

2)如果我通过简单地返回到Activity1并再次单击来重新启动Activity2,则会调用OnCreate()和其他常规生命周期中的方法,并且在执行从Mat到Bitmap的转换时,应用程序会崩溃,同时发生相同的致命信号错误:

Utils.matToBitmap(mCapturedFrame, bm); 

因此,这是第一次e重新启动活动后,OpenCV的函数被调用。最好的部分是,加载OpenCV库后,mCapturedFrame exsists和上述方法被称为。更重要的是,我释放()本地创建的Mats,以及包含捕获帧Mat的字段(当我从Activity2返回时)。在Activity1的情况下,该错误看起来像内存泄漏,但在哪里?

我真的不能看到我在这里做错了什么,并会很高兴的任何建议。随意从这里下载我的java代码文件:http://speedy.sh/RMPKH/thesis.zip

回答

1

如果我正确地理解了这一点,您将Mat的本地对象地址从Activity 1发送到Activity 2.然后,在Activity 2中,您正在这样的事情:

Mat receivingMat = new Mat(nativeAddrFromActivity1); 

在这种情况下,问题是,你运行到一个双免费的错误。这是不重要的,但我会引导你。首先,让我们看看OpenCV中的垫执行该构造的:

public Mat(long addr) 
{ 
    if (addr == 0) 
     throw new java.lang.UnsupportedOperationException("Native object address is NULL"); 
    nativeObj = addr; 
} 

当然,receivingMat将在未来超出范围的奔跑,然后一些点由GarbageCollector收集。在这种情况下,将调用finalize方法。这导致对OpenCV中的垫实施本地删除功能的调用,因为finalize方法是这样实现的:

@Override 
protected void finalize() throws Throwable { 
    n_delete(nativeObj); 
    super.finalize(); 
} 

的n_delete功能(see here)定义如下:

// 
// native support for java finalize() 
// static void Mat::n_delete(__int64 self) 
// 

JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1delete 
    (JNIEnv*, jclass, jlong self); 

JNIEXPORT void JNICALL Java_org_opencv_core_Mat_n_1delete 
    (JNIEnv*, jclass, jlong self) 
{ 
    delete (Mat*) self; 
} 

从我的观点是,这是OpenCV for Android中的一个错误。使用本机地址构造函数创建的Mat不应该调用n_delete函数,因为它没有本地Mat标头的所有权,并且不负责清除它。我不认为,你想这种行为无论如何...


解决你的问题,你应该垫,而不是转换为位图,保存到一个临时文件和发送的路径文件从活动1到活动2通过意向附加活动。

+0

谢谢你的回答。对不起,我写这么晚了。不幸的是,我无法检查解决方案是否有效,但您分析它的方式似乎很好。 我已经通过禁用后退按钮功能处理了这个问题(我简单地从活动XML配置中删除了“父活动”属性)。 – przemulala