Search code examples
csegmentation-faultmallocfreedynamic-memory-allocation

Freeing an invalid pointer?


void resolve_paths(char* inputdir)
{
    char** tokens = malloc(64*sizeof(char*));
    char* ptr;
    char* slash = "/";
    int i = 0;

    ptr = strtok(inputdir,slash);
    while(ptr != NULL){
        if(strcmp(ptr,"~") == 0){
            ptr = getenv("HOME");
        }
        tokens[i] = (char*)calloc(64,sizeof(char));
        tokens[i] = ptr;
        printf("token[%i] = %s\n",i,tokens[i]);

        i++;
        ptr = strtok(NULL,slash);
    }
    int j;
    printf("freeing each element of tokens\n");
    for(j = 0; j < i; j++){
        printf("freeing token[%i]\n",j);
        free(tokens[j]);
    }
    free(tokens);
    puts("leaving resolve_paths\n");
    return;
}

My Output:

before call
token[0] = a
token[1] = b
token[2] = c
freeing each element of tokens
freeing token[0]
freeing token[1]
Error in `./a.out': free(): invalid pointer: 0x00007ff96dca12b2 ***

I guess I simply don't understand how malloc/calloc and free work. Why does this code run into a seg fault?


Solution

  • tokens[i] = (char*)calloc(64,sizeof(char));
    tokens[i] = ptr;
    

    This code doesn't do what you think it does. First you allocate 64 bytes and store the address in tokens[i], then you replace that address with ptr (thus losing the just allocated one which leaks away).

    Probably you meant something like

    tokens[i] = calloc(64,sizeof(char));
    strncpy(tokens[i], ptr, 64);
    

    which allocates the memory and then copy the string pointed by ptr into it. Mind that you don't need to cast the result of calloc or malloc in C since a void* is implicitly convertible to any other pointer.

    In the end you try to free(tokens[i]) but the address contained is just a local address of inputdir adjusted by strtok, so it's not a dynamically allocated address which you can correctly free, that's why you get the error.