2012-03-05 2 views
6

Учитывая это C++ кода:ЮНА Утечка память

void LoadData(char** myVar) 
{ 
    std:: string str("[Really Long String Here]"); 
    unsigned int size = str.length() + 1; 
    *myVar = new char[size]; 
    strncpy(*myVar, str.c_str(), size); 
} 

И это ЮНА Ja:

Pointer myVar = new Memory(Pointer.SIZE); 
this.Lib.LoadData(myVar); 
this.someVar = myVar.getPointer(0).getString(0); 

У меня утечка памяти, как я понимаю, getPointer (0) следует создать указатель объект, который должен быть выпущен на finalize(), но, похоже, этого не происходит.

Я что-то упустил? Это похоже на spec ... и я могу запустить функцию выше, без утечек в C++.

Я вызываю Java-код в цикле, чтобы протестировать утечку, я попытался вставить паузы и вручную вызвать GC, также он быстро раздувается до гигабайтов.

Я уже несколько дней ударяю головой об этом, и это отстойно зависеть от чего-то настолько пустякового, как попытка освободить память. Насколько я могу судить, я могу только вручную освобождать память на Java, если У меня есть адрес, но я не вижу, как это получится.

Edit:

Nevermind, я даже не думаю, что есть способ сделать вручную бесплатно через ЮНА, не расширяя его ...

ответ

3

Добавьте эту функцию в библиотеку C++ ...

void FreeData(char** myVar) 
{ 
    delete [] *myVar; 
} 

А затем сделать этот ЮНА код

Pointer myVar = new Memory(Pointer.SIZE); 
this.Lib.LoadData(myVar); 
this.someVar = myVar.getPointer(0).getString(0); 
this.Lib.FreeData(myVar); 

Таким образом, вы выделить и удалить память в C++.

+0

Это пока работает, но нет ли в JNA другого способа освободить данные? :( – StrangeWill

+1

JNA - это просто оболочка для родной библиотеки. Она не управляет встроенной памятью, в особенности прямым собственным буфером. Задача разработчика собственной библиотеки - предоставить интерфейсы для выделения/освобождения памяти, которую использует библиотека. – ecle

+1

JNA внутренние методы для освобождения памяти, просто странные, что я должен был бы реализовать его снова, потому что все это защищено в JNA. – StrangeWill

0

Вместо MYVAR = новый символ [размер]

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

*myVar = malloc(size); 
strncpy(*myVar, str.c_str(), size); 

Массивы должны быть удалены, как: удалить [] * MYVAR;

JNA prolly не знает, как это сделать.

+1

'strlen (size)'? –

+0

Спасибо за хэдз-ап, Никлас, отредактирован. –

+0

Все еще течет, так же быстро. :( – StrangeWill

1

Ассигновать в вызывающем, а не вызываемом.

Например:

int LoadData(char* buf, int maxlen) { 
    std:: string str("[Really Long String Here]"); 
    strncpy(buf, str.c_str(), maxlen); 
    if (str.length() < maxlen) 
     return str.length(); 
    return maxlen; 
} 

Тогда при вызове из Java, пройти в byte[] соответствующего размера. Обратите внимание, что эта реализация потенциально очень неэффективна, но идея состоит в том, что вы обычно не хотите выделять память в одном контексте и освобождать ее от другого.

+1

В реализации: char * buf может быть 10 байт, 10k или 150k, возможно, больше, когда я реализую полный код. Вместо того, чтобы просто выделять несколько мегабайт и просто мириться с неэффективной реализацией (мое программное обеспечение может, m больше интересуется _right_ способом сделать это с помощью JNA). – StrangeWill

+0

Если вы хотите, чтобы вызывающий управлял хранилищем, вы можете вернуть «const char *»; JNA скопирует содержимое в строку Java, после чего вы чтобы изменить содержимое буфера и/или удалить его.Если вы вернете указатель, вы можете избежать копирования памяти до тех пор, пока на стороне Java не будет необходимости смотреть на данные. «Правильный» способ сделать это сильно зависит от того, какие части (java или native) вашей программы должны получить доступ к данным, как часто и как долго будет работать буфер. – technomage