2016-08-19 8 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を()を呼び出すべきではありません。

これは、J11で実装しているときに、X11関数のマニュアルページを読むことが混乱していることを意味します。これらのmanページはXFreeを使用して返されたリソースをクリーンアップするように指示することがよくあります。

1

XTextProperty構造体のvalueフィールドにポインタを移動し、構造体自体は解放しません。 XTextProperty man pageから

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

あなたのコードから(valueフィールドがPointerいうよりStringでなければならないことに注意してください):要するに

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