Reputation: 3
I have a library in c++ and I am writing JNI wrapper functions to allow me to call it from JAVA. I have got a lot of different functions working but I am having a problem with one in particular.
The function I am trying to wrap looks like:
void Set_Name(std::string invar)
I have matching calls to GetStringUTFChars and ReleaseStringUTFChars as follows:
JNIEXPORT void JNICALL Java_com_metcarob_mys_javaapi_a_1SM_1D_1Orginisation_Set_1Name
(JNIEnv *p_jEnv, jobject p_jObj, jlong p_nat, jstring invar) {
SM_D_Orginisation* p_SMD = (SM_D_Orginisation*) p_nat;
const char *pPp_invar2 = p_jEnv->GetStringUTFChars( invar, NULL );
if (NULL==pPp_invar2) return;
std::string *pPp_invar = new std::string(pPp_invar2);
p_SMD->Set_Name(*pPp_invar);
pPp_invar2 = pPp_invar->c_str();
p_jEnv->ReleaseStringUTFChars(invar, pPp_invar2);
SAFE_DELETE(pPp_invar);
}
I am getting an invalid pointer exception when I run this from Java:
*** glibc detected *** /home/robert/Oracle/Middleware/jdk160_21/bin/java: free(): invalid pointer: 0x0841a744 ***
======= Backtrace: =========
/lib32/libc.so.6(+0x6b511)[0xf7637511]
/lib32/libc.so.6(+0x6ce1b)[0xf7638e1b]
/lib32/libc.so.6(cfree+0x6d)[0xf763bf8d]
/home/robert/Oracle/Middleware/jdk160_21/jre/lib/i386/client/libjvm.so(+0x34fc8c)[0xf703bc8c]
/home/robert/Oracle/Middleware/jdk160_21/jre/lib/i386/client/libjvm.so(+0x25139a)[0xf6f3d39a]
/home/robert/Encrypted/Projects/Scout_Management/smbackend/DEBUG/libjavaapi.so(_ZN7JNIEnv_21ReleaseStringUTFCharsEP8_jstringPKc+0x27)[0xe02475c9]
/home/robert/Encrypted/Projects/Scout_Management/smbackend/DEBUG/libjavaapi.so(Java_com_metcarob_mys_javaapi_a_1SM_1D_1Orginisation_Set_1Name+0xd8)[0xe0245467]
[0xf4c0105d]
If I remove the call to ReleaseStringURFChars it works without a problem. Documentation states that I must call ReleaseStringUTFChars for every call I make to GetStringUTFChars to prevent memory leaks.
I have no idea what I am doing wrong or what I should be checking.
Can anyone assist?
Thanks
Robert
Upvotes: 0
Views: 1364
Reputation: 12489
You first acquire the pointer with
const char *pPp_invar2 = p_jEnv->GetStringUTFChars( invar, NULL );
But then you reassign the pointer with
pPp_invar2 = pPp_invar->c_str();
You must first first release the memory, then reassign the pointer.
Also, you don't need to allocate pPp_invar
with new
and then delete it, a simple p_SMD->Set_Name(pPp_invar2);
should suffice.
Upvotes: 2