Tushar Sudake
Tushar Sudake

Reputation: 1178

char* value changes after function return

Didn't find similar question, so opening a new one.

I'm trying to pass a Java object to JNI layer in my program and extract Java String field in it. The extracted field is set in the C struct.

I'm seeing a strange behavior. I'm able to extract the required fields successfully and memcpy it in the struct field. But when my utility function returns, the field set in struct get corrupted. I suspected a memory leak and rechecked, but nothing looks suspicious (I'm not doing much dynamic memory stuff code..just one malloc and free.)

Here goes the code:

Header File:

typedef struct Job {
   char* job_id;
} Job;

C File:

JNIEXPORT jint JNICALL Java_com.test.JobHandler__1submitJob(
        JNIEnv *env, jobject this, jobject job) {       
    current_job = (Job *) malloc(sizeof(Job));
    convert_job(env, job, current_job);
    free(current_job);
}

void convert_job(JNIEnv *env, jobject javajob, Job *job) {
    jclass cls = (*env)->GetObjectClass(env, javajob);    
    getVoidStringField(env, cls, javajob, job->job_id, "getJob_id");
    //job->job_id gets corrupted here
}

void getVoidStringField(JNIEnv *env, jclass cls, jobject obj, char *jobStr, char *methodName) {
    jmethodID mid = (*env)->GetMethodID(env, cls, methodName, "()Ljava/lang/String;");
    jobject js =  (*env)->CallObjectMethod(env, obj, mid);
    const char *str = (*env)->GetStringUTFChars(env, js, 0);
    int len = (*env)->GetStringUTFLength(env, js);
    jobStr = (char*) malloc(len);
    memcpy(jobStr, str, len);
    jobStr[len] = '\0';
    (*env)->ReleaseStringUTFChars(env, js, str);
    //jobStr is fine till here.
}

I removed other stuff from my code and reduced to above version to simply debugging, still same issue.

If I pass modify getVoidStringField(...) a bit to accept Job object and then work on job->job_id, it works fine.

Curious to know. I doubt it has something to do with JNI.

Upvotes: 0

Views: 313

Answers (1)

racraman
racraman

Reputation: 5034

Couple of things :
When you pass in job->job_id, you are passing in the VALUE of that pointer, not the pointer itself. That means when you do the jobStr = (char*) malloc(len);, you are not changing job->job_id, but just that function's local variable.

So, what you need to pass in is &(job->job_id), and the parameter should be char **jobstr

Your malloc would then be (not forgetting to allow for the null terminator):

*jobStr = (char*) malloc(len +1);

and, of course, the following statements should refer to *jobstr

Upvotes: 2

Related Questions