2016-08-19 2 views
0

낮은 레벨의 X11 프로그래밍을 수행하는 경우 일반적으로 반환되는 구조체에서 XFree()를 호출해야합니다. 그 문제가 사라 제거하면 예를 들어 XGetWMName를 들어, 나는 다음이가 XFree() 호출에 의해 발생JNA X11 및 XFree

AssertionMessage: *** Error in `/opt/jdk1.8.0_40/bin/java': double free or corruption (fasttop): 0x00007f7ca822bdd0 *** 

으로 몇 초 후에 불면 다음 코드에서 이런 짓을했습니다. 그러나 상단의 과정을 모니터링하는

public class X11WindowFinder { 

    private X11 x11; 

    public X11WindowFinder() { 
     x11 = X11.INSTANCE; 
    } 

    public List<Window> find(Pattern title) { 
     Display display = x11.XOpenDisplay(null); 
     Window root = x11.XDefaultRootWindow(display); 
     List<Window> windows = recurse(x11, display, root, title); 
     x11.XCloseDisplay(display); 
     return windows; 
    } 

    private synchronized List<Window> recurse(X11 x11, Display display, Window root, Pattern pattern) { 
     List<Window> windows = new ArrayList<>(1); 
     X11.WindowByReference windowRef = new X11.WindowByReference(); 
     X11.WindowByReference parentRef = new X11.WindowByReference(); 
     PointerByReference childrenRef = new PointerByReference(); 
     IntByReference childCountRef = new IntByReference(); 

     x11.XQueryTree(display, root, windowRef, parentRef, childrenRef, childCountRef); 
     if (childrenRef.getValue() == null) { 
      return Collections.emptyList(); 
     } 

     long[] ids = {}; 

     if (Native.LONG_SIZE == Long.BYTES) { 
      ids = childrenRef.getValue().getLongArray(0, childCountRef.getValue()); 
     } else if (Native.LONG_SIZE == Integer.BYTES) { 
      int[] intIds = childrenRef.getValue().getIntArray(0, childCountRef.getValue()); 
      ids = new long[intIds.length]; 
      for (int i = 0; i < intIds.length; i++) { 
       ids[i] = intIds[i]; 
      } 
     } 

     for (long id : ids) { 
      Window child = new Window(id); 
      X11.XTextProperty name = new X11.XTextProperty(); 
      x11.XGetWMName(display, child, name); 
      String value = name.value; 
      if (value != null) { 
       System.out.println(String.format("Found window %s free %s", value, name)); 
      } 
      if (value != null && pattern.matcher(value).matches()) { 
       windows.add(child); 
      } 
      x11.XFree(name.getPointer()); 
      windows.addAll(recurse(x11, display, child, pattern)); 
     } 
     return windows; 
    } 

    public static void main(String[] args) { 
     X11WindowFinder finder = new X11WindowFinder(); 
     while (true) { 
      finder.find(Pattern.compile(".*Firefox.*")); 
     } 
    } 

} 

JNA의 포인터가 사용 가능한 메모리에 마무리()를 사용 보인다 ... 나는 그것을 필요로 할 제안 지속적인 메모리 증가를 보여줍니다 즉 com.sun.jna.Memory.finalize()

/** Properly dispose of native memory when this object is GC'd. */ 
protected void finalize() { 
    dispose(); 
} 

그래서 XFree()를 호출하면 이중 할당이 취소 될 위험이 있습니다.이 가정은 정확합니까? JNA, 특히 X11 플랫폼과 관련된 몇 가지 예를 찾을 수 있습니다.

+1

XLib은 'XTextProperty'를 할당하지 않습니다. 당신은'new X11.XTextProperty()'를 가지고 그것을 할당한다. 따라서''XFree ''해서는 안됩니다. –

답변

0

JNA Java 객체가 가비지 수집 될 때 com.sun.jna.Memory.finalize()가 자동으로 JNA를 해제합니다.

/** Properly dispose of native memory when this object is GC'd. */ 
protected void finalize() { 
    dispose(); 
} 

/** Free the native memory and set peer to zero */ 
protected synchronized void dispose() { 
    free(peer); 
    peer = 0; 
    allocatedMemory.remove(this); 
} 

당신은 당신이 경우에 원래의 질문 "double free or corruption (fasttop)"에 설명 된대로 "더블 해제"오류 위험) XFree를 (호출하지 않아야합니다.

이것은 JNA로 구현할 때 X11 기능의 매뉴얼 페이지를 읽는 것이 혼란 스럽다는 것을 의미합니다. 이 맨 페이지는 XFree를 사용하여 반환 된 리소스를 정리하도록 지시합니다.

1

구조 자체가 아닌 XTextProperty 구조의 value 필드에서 포인터를 해제하려고합니다. XTextProperty man page에서

:

To free the storage for the value field, use XFree. 

코드에서합니다 (value 필드가되어야한다고합니다 메모 Pointer 오히려 String (A)보다) : 메모리에 의해 내부적으로 관리 요약

x11.XTextProperty name = new X11.XTextProperty(); 
x11.XGetWMName(display, child, name); 
// ... do some stuff 
x11.XFree(name.value); 
+0

답장을 보내 주셔서 감사합니다. 코드 예제를 제공해 주시겠습니까? 이것은 X11에 대한 JNA 바인딩이므로, 서명은 XFree (com.sun.jna.Pointer)이므로 x11.XFree (name.getPointer()) 이외의 전달 방법을 볼 수 없습니다. – Adam