2012-07-17 5 views
1

따라서 아래 코드는 finalize 중에 segfaults입니다.GMP 용 JNA 래퍼에서 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 개 정도의 구조체를 적절히 파괴합니다.

+0

문제는 C면에 있습니다. 코드를 작성하지 않았다면 라이브러리를 올바르게 사용하고 있는지 다시 한 번 확인하십시오. –

+0

나는 그것을 올바르게 사용하고 있다고 확신한다. 다른 함수 바인딩은 훌륭하게 작동하며 매우 잘 계산할 수 있습니다. GMP 문서에서 다음과 같이 말합니다 : _/* 프로그램이 종료되지 않는 한 ... */mpz_clear (integ); _ __gmpz_clear 함수는 위의 코드에 대한 Java 바인딩이며, java/scala가 struct 객체로 완료 될 때만 호출됩니다. – MarkHammons

+0

스타일의 문제로 allocateMemory() 및 ensureAllocated()가 불필요합니다. constructor 내에서 상기 메모리에 대해 몇 가지 연산을 수행해야하는 경우 ensureAllocated() (allocateMemory())를 호출하면됩니다. – technomage

답변

0

그래서 내 자신의 문제에 대한 해결책을 찾았습니다. 해결책은 현재 반 해키 (semi-hacky)입니다.

__gmpz_clear에 대한 JNA 호출이 가비지 수집기와 다른 스레드에 있고 가비지 수집기가 실행을 완료하기 전에 포인터 데이터와 다른 것들을 파괴하는 경우가 있습니다. while(_mp_size > 0) ;을 통해 스핀 록을 추가하면 문제가 완전히 해결됩니다. 정리를 보장하기 위해

+0

기술적으로, '구조체'자동 할당 메모리의 파이널 라이저가 '구조체'인스턴스의 파이널 라이저 후에 * 실행되는지 확인하려고합니다. 하나의 파이널 라이저가 가비지 수집기와 다른 스레드에서 실행되는 것은 아닙니다. – technomage

0

는 이전에 실제로 할당 된 메모리를 해제 기존 파이널에 __gmpz_clear를 호출하는 기존의 파이널을 증대 사용자 정의 Memory 개체를 반환 최우선 Structure.autoAllocate(int size)을 고려해 볼 수 있습니다, 적절한 순서로 실행됩니다.

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

이 문제는 불행히도 해결되지 않습니다. 내 솔루션은 완전히 (아직 segfaults 때로는) 그것을 해결하지 않지만 그것은 대부분의 시간을 작동합니다. – MarkHammons

+0

'Native.setProtected (true)'를 사용하면 segfault의 스택 추적은 무엇입니까? – technomage

+0

__gmpz_clear를 참조로 전달하지 않고 값으로 전달하도록 변경하면 모든 segfault 문제가 해결되지만 메모리가 여전히 누출됩니다. 내 원래 솔루션과 함께. – MarkHammons