2016-06-23 40 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