NewStringUTF() and freeing memory

rid picture rid · Jun 4, 2011 · Viewed 49.6k times · Source

Should I free the allocated string after passing it to NewStringUTF()?

I have some code similar to:

char* test;
jstring j_test;

test = some_function(); // <- malloc()s the memory
j_test = (*env)->NewStringUTF(env, test);

free(test); // <- should this be here?

When I free the string after passing it to NewStringUTF(), I get a signal 11 (SIGSEGV), fault addr deadbaad error. If I remove the free() call, the error vanishes. What am I doing wrong?

I see conflicting opinions. Some say I should free it myself, some say the VM frees it, some say the VM doesn't free it and you should do strange voodoo magic to free it. I'm confused.

Answer

fizzer picture fizzer · Jun 5, 2011

The storage for the const char* argument to NewStringUTF() is entirely your responsibility: if you allocated test with malloc(), then you need to free() it. So, the snippet you posted is correct. You are corrupting the heap somewhere else.

I see conflicting opinions. Some say I should free it myself, some say the VM frees it, some say the VM doesn't free it and you should do strange voodoo magic to free it. I'm confused.

They are talking about the jstring instance returned by NewStringUTF(). That follows the confusing rules for 'local references'.

It is never an error to release this reference with DeleteLocalRef() when you are finished with it. However, the JVM performs some dubious magic if you call NewStringUTF() in the context of a JVM thread. When the native method returns to Java, any leaked local references are automatically cleaned up. So if you are sure your ultimate caller is in a Java thread, then you can safely leak the reference.

On the other hand, if you are running in the context of a native thread - say, some event reporting thread making callbacks to Java - there never is a return to Java, so you must call DeleteLocalRef() yourself on this jstring (and indeed all the other local references returned by typical JNI calls).