I've been researching this for a day and I've found a lot of conflicting information on multiple websites. I'm writing a simple test that will allocate and initialize a char** (array of strings, char*). I've distilled the code down to the relevant parts below. I'm running this on Linux with Eclipse IDE for C/C++.

I do realize that I could just create a simple char arr[rows][cols]; of whatever size but I want this test to create dynamic memory on the heap.

After the char** arr malloc, I've read to do multiple things and I can't tell which is one right or wrong because even running with Valgrind, I get no errors. Therefore, what is the best practice way to accomplish the questions inline with the code below?

void init_str_list(uint size) {
    if (size == 0) {
    fprintf(stderr, "Cannot allocate an array of size 0.");
    return;
    }

    // Allocate enough memory plus the NULL of the list array.
    char** arr = (char**)malloc(sizeof(char*) * size + 1);

    if (arr == NULL) {
        fprintf(stderr, "Unable to allocate string array.");
    return;
    }

    // QUESTION: How to properly initialize arr?
    // I've seen multiple examples of such:
    // 1) arr[0] = NULL;  // If not sure if this is really needed like it is for a single char*
    // 2) arr[size - 1] = NULL;  // I would think this must always be done.
    // 3) Some places say to do nothing though if so, draws into question of malloc "size + 1"
    // 4) I've even seen where one is supposed to loop arr and NULL each arr[i].

    // Valdrind will give no errors if these are commented or uncommented
    // I suppose because we are initializing each string in the array
    // below?
//  arr[0] = NULL;
//      arr[size - 1] = NULL;
//      Do nothing?

    // Cap the array at 30 bytes.
    size_t len = 30;
    for (int i = 0; i < size; i++) {
        // I know, should check for NULL after the malloc but for brevity, assume 
        // it allocated OK.
    arr[i] = (char*)malloc(sizeof(char) * len + 1);

        // QUESTION: Should there be a null terminated like below even
        // though snprintf NUL terminates it?
    // arr[i][0] = '\0';

        // snprintf appends the NUL at the end.
    snprintf(arr[i], len, "arr[%d] = %d", i, i);
    }

    for (int i = 0; i < size; i++) {
    printf(arr[i]);
    free(arr[i]);
    }

    free(arr);
}

To summarize, I'm looking for the best practice for null terminating the char** and in this example, nul terminating each char* in the char** since I'm using snprintf. There is just so much conflicting information on how to properly do this.

Any help would be much appreciated.

2 Replies 2

You don't need to do anything. If you were allocating an array of char* up front and only doing things with each slot gradually further down in the code, it would be prudent to loop through and set them all to null, but if you are assigning a value to each one right away, as you do here, doing that up-front initialization would just be wasteful.

Something similar applies to your commented-out arr[i][0] = '\0' assignment. As you are immediately doing snprintf into that same pointer, there's no point in zero-terminating it right before - the zero-terminator would get overwritten immediately.

Somewhat offtopic, but consistent formatting and indentation makes your code easier to read.

Especially when you come back in a few months and have to figure out what deranged ideas drove you to write the crazy code you can't understand.

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.