1

I am just starting to learn about malloc'd and realloc'd arrays. Can anyone help explain to me how to properly free my following array? I have tried looking at other posts, but I have a hard time understanding memory allocation in C.

char ** result = NULL;
int numSpaces = 0;

char * p = strtok(command, " ");

/* split string and append tokens to 'result' */
while (p)
{
    result = realloc (result, sizeof (char*) * ++numSpaces);

    if (result == NULL)
        exit (-1); /* memory allocation failed */

    result[numSpaces-1] = p;

    p = strtok(NULL, " ");
}
ravron
  • 11,014
  • 2
  • 39
  • 66
Peter
  • 498
  • 3
  • 15

2 Answers2

4

Freeing realloc-ed memory is not different from freeing malloc-ed memory, in that all you need is to call free on the result at the end, when you no longer need the memory.

Your code, however, has a pattern that may lead to a memory leak: you are assigning realloc-ed block back to result without checking it for NULL. If realloc fails, the previous value of the result becomes unrecoverable, because it has been overwritten by NULL.

Here is how you could fix this issue:

char **temp = realloc(result, sizeof (char*) * ++numSpaces);

if (temp == NULL) {
    free(result); // Free the old memory block
    exit (-1); /* memory allocation failed */
}
result = temp;
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • They are checking for that case. `if (result == NULL)`. And they handle it by killing the application. – Bill Lynch Apr 11 '15 at 14:11
  • 1
    @BillLynch They null-check allocation, but that's too late: the old `result` is gone by then. – Sergey Kalinichenko Apr 11 '15 at 14:13
  • Thank you, it works now. I was looking at some examples and they had free() in a for loop and other stuff going on so I was a bit unsure. Cheers! – Peter Apr 11 '15 at 14:14
  • There is no memory leak, because the code terminates the program when realloc fails. Worrying about freeing on exit is an operating-system-specific problem. On a system that cleans up processes properly, it's just a waste of cycles to iterate over data structures and free them. For programs that juggle a large number of objects, it can create significant delays in shutdown, especially if they are paged out to disk. – Kaz Apr 11 '15 at 14:20
  • @Kaz This is a learning exercise, not a production system. It's important to learn the right patterns from the beginning to avoid mistakes when writing production code where the system is not exiting on `realloc` failures, but does something else. – Sergey Kalinichenko Apr 11 '15 at 14:35
3

At some point after you are done using result, you need to call free(result);.

This might look like:

char ** result = NULL;
int numSpaces = 0;

char * p = strtok(command, " ");

while (p) {
    result = realloc (result, sizeof (char*) * ++numSpaces);
    result[numSpaces-1] = p;
    p = strtok(NULL, " ");
}

for (i=0; i<numSpaces; ++i)
    printf("word %d: %s\n", i, result[i]);

free(result);
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • Thank you, it works now. I was looking at some examples and they had free() in a for loop and other stuff going on so I was a bit unsure. Cheers! – Peter Apr 11 '15 at 14:15