Освобождает ли JNA память возвращаемого значения Go CString - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть такой интерфейс JNA:


interface JJ {
    String Hello(GoString.ByValue sql);
}

Соответствующий нативный код в Go:


//export Hello
func Hello(ss string) *C.char {

    s := ss + " world"
    return C.CString(s)
}

Нативный код возвращает указатель на строку.

Освобождает ли код JNA указатель строки, выделенной собственным кодом? Если нет, то как его освободить?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Я отвечу как на общий вопрос, так и на конкретный пример.

JNA не поддерживает никаких ссылок на собственную память, если вы сами не выделите ее в JNA (например, определите массив byte[] илиMemory буфер, который вы передаете функции). В этих случаях собственная память освобождается, когда объект Java собирается мусором.

Если вы не передаете какую-либо память для заполнения C, JNA не собирается ничего делать с собственной памятью, ивам нужно прочитать документацию API, чтобы увидеть, какова ваша ответственность за освобождение нативной строки.

Тип Ctring C ++ не обязательно должен быть освобожден , если он не сохранен в новом объекте . Тем не менее, Go реализует CString как объект и документирует эти требования. Для вашего конкретного примера, документы говорят:

Распределение памяти, выполненное кодом C, не известно менеджеру памяти Go. Когда вы создаете строку C с C.CString (или любым выделением памяти C), вы должны не забыть освободить память, когда закончите с ней, вызвав C.free.

и из cgo wiki :

Важно помнить, что C.CString () выделит новую строку соответствующей длины и вернет ее. Это означает, что строка C не будет собираться мусором, и вы можете ее освободить. Стандартный способ сделать это следующим образом.

// #include <stdlib.h>

import "C"
import "unsafe"
...
    var cmsg *C.char = C.CString("hi")
    defer C.free(unsafe.Pointer(cmsg))
    // do something with the C string

Конечно, вы не обязаны использовать defer для вызова C.free (). Вы можете освободить строку C, когда захотите, но вы обязаны убедиться, что это произойдет.

0 голосов
/ 10 ноября 2019

Получите Java для выделения буфера, чтобы он вместо этого освободил его для вас .. в противном случае вы ДОЛЖНЫ освободить его самостоятельно и экспортировать функции освобождения.

public interface JJ {
    JJ lib = (JJ)Native.loadLibrary("jj.so", JJ.class);

    void Hello(byte[] sql);
}

func Hello(ss []byte) {
    copy(ss[:], string(ss) + " world")
}

Использование:

void main(String[] args) {
    byte[] text = new byte[256];

    JJ.lib.Hello(text);

    System.out.println(Native.toString(text));
}

Вы можете обернуть все это в универсальную функцию, которая создаст для вас строку для любой данной нативной функции ... но вы поняли.

  1. Java выделяет буфер, Go-Lang заполняет его,Java освобождает его автоматически.
  2. Go-Lang выделяет буфер, Java использует его, Go-Lang освобождает его.

В обоих случаях тот, кто выделяет буфер, должен его освобождать.

...