Search code examples
cfreedynamic-memory-allocation

Freeing an array of dynamically allocated pointers


I'm studying for an exam, and I have a question about a sample question that I was provided:

Implement the function free_array with prototype void free_array(void *a[], int length). The purpose of the function is to free the dynamically allocated memory associated with each array element in the first parameter passed to the function. The function must handle the scenario in which two or more array entries point to the same memory (only one free can be applied to a single memory location).

My first thought was to set each freed index to NULL because calling free() on NULL is harmless. So I did the following:

void free_array(void *a[], int length) { 
   int i;
   for (i = 0; i < length; i++) {
      free(a[i]);
      a[i] = NULL;
   }
}

The solution provided is pretty different than mine, and I don't fully understand what they're doing. Here's what I'm given as the answer:

void free_array(void *a[], int length) { 
    int i, j;
    for (i = 0; i < length; i++) {
        if (a[i] != NULL) {
            free(a[i]);
            for (j = i + 1; j < length; j++) {
                if (a[j] == a[i]) {
                    a[j] = NULL;
                }
            }
        }
    }
}

I'm really confused about what's going on here. It seems like they're freeing each entry and marking the ones with the same content to NULL. However, I thought that we aren't supposed to re-access freed memory? Also, would my way still work?


Solution

  • E.g.

    Say you have an array of strings

    char* ar[5]; 
    

    you allocate some strings and let 0 and 4 index point to the same allocated string

    ar[0] = ar[4] = strdup("mycommonstring");
    ar[1] = strdup("hello");
    ar[2] = strdup("world");
    ar[3] = strdup("!");
    

    With you answer you will free what ar[0] points to first, unfortunately ar[4] is still pointing to the same memory location, but when free(ar[0]) is called, the memory location it points to is invalid. When free is later called on ar[4], it will cause an error.

    The given example makes sure that all pointers that point to the same location will be set to NULL to avoid that an invalid address is passed to the free function. So no, the memory location is not accessed again, only the pointer to the memory location