1

そのため、ファイナライズ中に以下の Java コード segfaults が発生します。

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側の構造体を破壊します。その部分を切り取ると、segfault は発生しませんが、コードでメモリ リークが発生します。誰でもこれについてアイデアがありますか?

私はそれが確実にセグメンテーション違反をしないことを付け加えるかもしれません。問題が発生する前に、これらの構造体のうちおそらく 20 個を適切に破棄します。

4

2 に答える 2

0

だから私は自分の問題に対する答えを見つけました。解決策は現在セミハッキーです。

問題は、JNA 呼び出しが__gmpz_clearガベージ コレクターとは異なるスレッド上にあり、__gmpz_clear実行が完了する前にガベージ コレクターがポインター データやその他のものを破壊する場合があることです。スピンロック ビアを追加while(_mp_size > 0) ;すると、問題は完全に解決されます。

于 2012-07-17T20:11:18.183 に答える
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();
            }
        };
    }
}

これにより、メモリが解放される前に常に「クリア」されることが保証されます。

于 2012-07-17T20:24:04.863 に答える