cpointersdouble-pointer

First element of double pointer array is always "garbage"


when using qsort() to try and organize an array of pointers I always get garbage on the first element of the double pointer. I have a suspicion that it's pointing to the wrong memory address and I'm just not understanding.

I'm pretty pretty new to C (about 3-4 weeks) and if someone could help me understand why I'm getting the bad value and suggest how I could get around the problem I would appreciate it.

code:

    char *token;
    char **string_array = calloc(wordcount, sizeof(char));
    if (!string_array){
        fprintf(stderr, "couldn't make double pointer\n");
    }
    size_t str_array = 0;

    token = strtok(w2->data, "\n\t ");
    printf("token %ld: %s\n",str_array, token);
    size_t tok_len = strlen(token);
    string_array[str_array] = calloc(tok_len,sizeof(char));
    if (!string_array[str_array]){
        fprintf(stderr, "could not find any of your words\n");
        return;
    }
    if (!strncpy(string_array[str_array++], token, tok_len)){
        return;
    }
    
    for (int x = 1; x<wordcount; x++){
        token = strtok(NULL, "\n\t ");
        tok_len = strlen(token);
        string_array[str_array] = calloc(tok_len,sizeof(char));
        if (!string_array[str_array]){
            fprintf(stderr, "failed somewhere with other tokens\n");
            return;
        }
        printf("token %ld: %s\n",str_array, token);
        if (!strncpy(string_array[str_array++], token, tok_len)){
            puts("could not find one of your words\n");
            return;
        }
    }
    qsort(string_array, str_array, sizeof(*string_array), lexsort);

    for (int x = 0; x<wordcount; x++){
        printf("%s\n",string_array[x]);
    }
    return;
}

the output of the program looks like:

**//shows me what flags the user has set**
a selected
this is the most recent character: a

**//debugging though print statements**
The struct was made
gathering words
Allocated space

** //lines of words read in from file passed on the command line**
token 0: is
token 1: a
token 2: file
token 3: of          
token 4: 123:LK
token 5: words
token 6: 123456789

**//output after the array has been sorted**
123456789
123:LK
        **//this blank spot is the first element of the array and sometimes it's random garbage from memory (depending on the word)**
a                    
file
of
words

Already tried:

I thought if I expanded the double pointer array +1 (calloc((wordcount + 1), sizeof(char)) and started added the elements at the first index of the array instead of the zeroth index (str_array = 1;) it might help but it just seg faults (naturally...)


Solution

  • First, double pointers are pointers that point to pointers, so in the calloc you must use char * instead of char and you should remember to initialize inner pointers too, which you actually did here string_array[str_array] = calloc(tok_len,sizeof(char));.

    Second, strings in C are null terminated which means C stores Hello as H e l l o NULL so when you have strlen equals to 5 you need an array of 6 elements to store it.

    string_array[str_array] = calloc(tok_len,sizeof(char) + 1);
    

    The following line in your code is correct:

    if (!strncpy(string_array[str_array++], token, tok_len)){
            return;
        }
    

    but it is better to write it as to make more readable:

    if (!strncpy(string_array[str_array], token, tok_len)){
            return;
        }
    str_array++;
    

    About the qsort, I think it is correct and will work as expected. Again, using sizeof(char *) is more readable than sizeof(*string_array).