Search code examples
carraysstructmallocdynamic-memory-allocation

Don't I have to malloc() this array?


I'm struggling to learn the C rules of malloc() / free(). Consider the below code, which runs just fine. (On Linux, compiled with GCC.) Specifically, I'm wondering about the arr array. I get that you have to malloc for all the struct elements within the array... but why don't you have to malloc for the array itself?

#include<stdio.h>
#include<stdlib.h>
#define ARR_SIZE 100

typedef struct containerStruct{
    int data1;
    int data2;
    int data3;
    // ...etc...
} container;

int main(){

    container* arr[ARR_SIZE];       // Don't I have to malloc this?

    int i;
    for(i=0; i<ARR_SIZE; i++){
            arr[i] = (container*) malloc (sizeof(container));   // I get why I have to malloc() here
    }

    ...do stuff...

    for(i=0; i<ARR_SIZE; i++){
            free(arr[i]);        // I get why I have to free() here
    }

    // Don't I have to free(arr) ?
    return 0;
}

I'm guessing that the container* arr[ARR_SIZE]; line tells the compiler all it needs to know to carve out the space in memory for the array, which is why this code works.

But it still doesn't "feel" right, somehow. When I malloc() something, I'm reserving memory space on the heap, right? But my container* arr[ARR_SIZE]; call creates the array on the stack. So... the array of container* porters exists on the stack, and all of those container* pointers point to a container struct on the heap. Is that correct?


Solution

  • Since ARR_SIZE is fixed member of the dynamic array *arr[ARR_SIZE], you no longer have to allocate memory for the whole array, but just the elements within it, as they are flexible in this case.

    When you malloc any sort of dynamic array, it is safe to always check the return value of the void* pointer returned from malloc. Additionally, when you free each element, it is even safer to set each member to NULL again, to prevent the pointer from accessing memory again.

    Illustrated through this code:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define ARR_SIZE 100
    
    typedef struct {
        int data1;
        int data2;
        int data3;
        // ...etc...
    } container_t;
    
    int
    main(void) {
        container_t *arr[ARR_SIZE];
        int i;
    
        for (i = 0; i < ARR_SIZE; i++) {
            arr[i] = malloc(sizeof(container_t));
            if (arr[i] == NULL) {
                printf("Malloc Problem here\n");
                exit(EXIT_FAILURE);
            }
        }
    
        for (i = 0; i < ARR_SIZE; i++) {
            if (arr[i]) {
                free(arr[i]);
                arr[i] = NULL;
            }
        }
    
        return 0;
    }