2012-07-17 38 views
1

因此,下面的java代碼segfaults在finalize期間。是什麼導致在此JNA包裝器中的段錯誤GMP

public class Mpz_t extends com.sun.jna.Structure { 
    public int _mp_alloc; 
    public int _mp_size; 
    public NativeLongByReference _mp_d; 

    protected void initFieldOrder() { 
     setFieldOrder(new String[] { "_mp_alloc", "_mp_size", "_mp_d" }); 
    } 

    public Mpz_t() { 
     super(); 
     initFieldOrder(); 
     allocateMemory(); 
     ensureAllocated(); 
    } 

    public static class ByReference extends Mpz_t implements 
     Structure.ByReference { 

    } 

    public static class ByValue extends Mpz_t implements 
     Structure.ByValue { 

    } 

    @Override public void finalize() { 
     Gmp.gmp().__gmpz_clear(this); 
    } 
} 

.__gmpz_clear()根據我的意識破壞C端的結構。如果我撕開那部分,沒有段錯誤,但是我的代碼會泄漏內存。任何人有關於此的想法?

我可能會補充說它並不可靠地發生段錯誤。在問題發生之前,它可能會正確地破壞這些結構中的20個。

+0

問題出在C端。如果您沒有編寫代碼,請仔細檢查您是否正確使用庫。 – 2012-07-17 19:48:26

+0

我很確定我正確地使用它。我的其他函數綁定工作得很好,我可以很好地計算它。在GMP文件,它說: _/*除非程序即將退出,做... */mpz_clear(INTEG); _ 的__gmpz_clear功能是java上面的代碼結合,並應只有當java/scala用struct對象完成時才被調用。 – MarkHammons 2012-07-17 19:50:16

+0

作爲一種風格,allocateMemory()和ensureAllocated()是多餘的。如果您需要在構造函數中對所述內存執行某些操作,則只需調用ensureAllocated()(它又調用allocateMemory())。 – technomage 2012-07-17 20:01:51

回答

0

所以我找到了我自己的問題的答案,解決方案目前是半哈克。

問題是JNA對__gmpz_clear的調用與垃圾收集器在不同的線程上,有時垃圾收集器在__gmpz_clear完成執行前破壞指針數據和其他內容。通過while(_mp_size > 0) ;添加自旋鎖完全解決了這個問題。

+0

從技術上講,你試圖確保'Structure'自動分配內存的終結器在你的'Structure'實例的終結器之後運行*。這不是一個終結器運行在與垃圾收集器不同的線程上。 – technomage 2012-07-17 20:15:08

0

爲了確保清理運行在正確的順序,你可能會考慮壓倒一切的Structure.autoAllocate(int size)返回定製Memory對象,擴充其現有的終結調用__gmpz_clear現有終結這實際上釋放所分配的內存之前。

public class Mpz_t extends Structure { 
    protected Memory autoAllocate(int size) { 
     return new Memory(size) { 
      protected void finalize() { 
       GMP.gmp().__gmpz_clear(this); 
       super.finalize(); 
      } 
     }; 
    } 
} 

這確保了存儲器是總是「清除」被釋放之前。

+0

這不能解決問題。我的解決方案沒有完全解決它(有時候它仍然存在段錯誤),但它大部分時間都有效。 – MarkHammons 2012-07-17 20:32:40

+0

當您使用'Native.setProtected(true)'時,segfault的堆棧跟蹤是什麼? – technomage 2012-07-17 20:38:39

+0

更改__gmpz_clear以通過值傳遞而不是通過引用傳遞修復所有段錯誤問題,但由於某些原因,內存仍然泄漏。同上我的原始解決方案。 – MarkHammons 2012-07-17 20:43:18

相關問題