Java 是什么导致此GMP JNA包装中的SEGFULT

Java 是什么导致此GMP JNA包装中的SEGFULT,java,jna,gmp,Java,Jna,Gmp,因此,下面的java代码在finalize期间会出现错误 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[] { "_m

因此,下面的java代码在finalize期间会出现错误

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);
    }
}
据我所知,
。\uuu gmpz\u clear()
在C端销毁结构。如果我删除了那个部分,就没有segfault,但我的代码会泄漏内存。有人对此有想法吗


我可以补充一点,这并不是一个错误。在出现问题之前,它可能会正确地破坏其中的20个结构。

因此我找到了自己问题的答案,目前的解决方案是半黑客的


问题是对
\uugmpz\u clear
的JNA调用与垃圾收集器在不同的线程上,有时垃圾收集器在
\ugmpz\u clear
完成执行之前销毁指针数据和其他内容。通过
while(\mp\u size>0)添加自旋锁完全解决问题。

为了确保清理按正确的顺序运行,您可以考虑重写<代码>结构。
返回自定义的
内存
对象,该对象扩充其现有终结器,在实际释放分配内存的现有终结器之前调用
\ugmpz\u 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();
            }
        };
    }
}

这可确保在释放内存之前,内存始终处于“清除”状态。

问题出在C端。如果您还没有编写代码,请仔细检查您是否正确使用了库。我很确定我使用的是正确的。我的其他函数绑定工作得很好,我可以很好地使用它进行计算。GMP文件中说:/*除非该计划即将退出,否则不要*/mpz_清除(整数);_u_gmpz_clear函数是上面代码的java绑定,只有在使用struct对象完成java/scala时才应该调用它。就风格而言,allocateMemory()和EnsureRealLocation()是多余的。如果需要在构造函数中对所述内存执行某些操作,则只需调用EnsureReallocated()(后者反过来调用allocateMemory())。从技术上讲,您试图确保自动分配内存的终结器在您的
结构
实例的终结器之后运行。这并不是说一个终结器与垃圾收集器在不同的线程上运行。不幸的是,这并不能解决问题。我的解决方案不能完全解决这个问题(有时仍然是segfaults),但它在大多数情况下都能正常工作。当您使用
Native.setProtected(true)
时,segfault的堆栈跟踪是什么?将u_gmpz_clear更改为按值传递而不是按引用传递可以修复所有segfaults问题,但由于某些原因内存仍然会泄漏。我的原始解决方案也是如此。re:按值传递-这是提供原始函数声明首先可以避免的错误。原始函数声明是
mpz\u clear(mpz\u t)
,因此,如果希望可靠执行,必须按值传递结构。您如何确定内存正在泄漏?