carrayspointerscharvalgrind

char** in function C and valgrind conditional jump erro


First of all my question is C only, not C++. I've search on SO and google my problem but I think it comes from a lack of understanding of both valgrind and some pointer in function argument in C so if someone could kindly explain to me, I'll be very grateful.

Here is my code in the main. The function getOrder is just supposed to cut the string after the ';' and send the second part (here "on") back in the bu variable buffer.

char na[] = "2;on";
char* bu="on";

//This part Do conditional jump
getOrder(na, 4, &bu);

//This part Doesn't do conditional jump
//char copy[strlen(na)];
//strcpy(copy, na);

//bu=strtok(na,";");

bu[2]='\0';

printf("ending : %s\n",bu); //(<- this is the line 54 of the valgrind error)

And here is the getOrder function :

//TODO conditional jump here ! Only whn returning from the function
char* getOrder(char order[], int size, char* res[]){
int i=0;
char copy[size];
strcpy(copy, order);

printf("\nstr: %s\n", copy);
*res=strtok(copy,";");
printf("tok : %s\n", *res);
*res=strtok(NULL, ";");
printf("tok : %s\n", *res); 
printf("%d and order is %s\n",strcmp(*res, "on"), *res);

return *res;
}

What I don't understand is why, when I use the getOrder function, Valgrind complains about all of this :

==7072== Conditional jump or move depends on uninitialised value(s)
==7072==    at 0x4E7EC15: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072== 
==7072== Conditional jump or move depends on uninitialised value(s)
==7072==    at 0x4EAEBC9: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072== 
==7072== Conditional jump or move depends on uninitialised value(s)
==7072==    at 0x4EAEBD7: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072== 
==7072== Syscall param write(buf) points to uninitialised byte(s)
==7072==    at 0x4F25E90: __write_nocancel (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4EAE49C: _IO_file_write@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4EAF948: _IO_do_write@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4EAEB5C: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E7EB55: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072==  Address 0x4022009 is not stack'd, malloc'd or (recently) free'd
==7072== 

But it doesn't when I use directly the same thing in the main. Basically those errors comes from the way I use the function getOrder (be it in the arguments, are the pointer I send) but I'm unable to find what is my mistake.

Thanks a lot for any help.


Solution

  • Because res end's up being a pointer to copy, and copy is deleted with the stack frame of getOrder function, since it's a local variable.

    try this

    // TODO conditional jump here ! Only when returning from the function
    char* getOrder(char order[], int size)
    {
        int i=0;
        char copy[size];
        char *res;
    
        strcpy(copy, order);
    
        printf("\nstr: %s\n", copy);
    
        res = strtok(copy, ";");
        if (res == NULL) /* always check the return value from strtok */
            return NULL;
        printf("tok : %s\n", res);
    
        res = strtok(NULL, ";");
        if (res == NULL) /* always check the return value from strtok */
            return NULL;
        printf("tok : %s\n", res);
        printf("%d and order is %s\n", strcmp(res, "on"), res);
    
        return order + (res - copy);
    }
    

    and the size parameter in your getOrder call should be 5 not 4, since there are 4 characters + the terminating null byte '\0'.

    char *na = "2;on";
    char *bu;
    
    //This part Do conditional jump
    bu = getOrder(na, 5);
    
    //This part Doesn't do conditional jump
    //char copy[strlen(na)];
    //strcpy(copy, na);
    
    //bu=strtok(na,";");
    
    //bu[2] = '\0';
    
    if (bu != NULL)
        printf("ending : %s\n", bu); //(<- this is the line 54 of the valgrind error)
    return 0;