Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JNA Memory Leak

Tags:

java

c++

c

jna

Given this C++ Code:

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);
}

And this JNA Java:

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

I'm having memory leaks, as I understand it, getPointer(0) should create a pointer object that should be released on finalize(), but it seems to not be.

Am I missing something? This seems up to spec... and I can run the function above with no leaks in C++ fine.

I call the Java code in a loop to test the leak, I've tried putting in pauses, and manually calling the GC, also it'll bloat to gigabytes rather quickly this way.

I've been banging my head against this for a few days now and it sucks to get hung up on something so trivial as attempting to free memory.As far as I can tell I can only manually free memory in Java if I have the address, but I can't see how I'd get that.

Edit:

Nevermind, I don't even think there is a way to do manually free through JNA without extending it...

like image 608
StrangeWill Avatar asked Mar 05 '12 15:03

StrangeWill


2 Answers

Add this function to the C++ library...

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

And then make this the JNA code

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

This way you allocate and delete the memory in C++.

like image 117
PatriotBob Avatar answered Oct 18 '22 05:10

PatriotBob


Allocate in the caller, not the callee.

For example:

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;
}

Then when you call from Java, pass in a byte[] of the appropriate size. Note that this implementation is potentially very inefficient, but the idea is that you don't generally want to be allocating memory in one context and deallocating it in another.

like image 33
technomage Avatar answered Oct 18 '22 07:10

technomage