Search code examples
cdynamic-memory-allocationrealloccalloc

Dynamic memory allocation for char***


I was trying to dynamically allocate memory for a char***.

char*** tas;

With char*** i want to describe a table of strings with 2 columns only.

Main problem i had trying to achieve that is not to compile the program but make it run without a segmentation fault.

The issue i think is the not proper use of realloc. Checking man page of realloc/calloc/malloc

void *realloc(void *ptr, size_t size);
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);

I found out that i have to generate the proper size_t vars to send to allocate functions.

The crucial lines of code for this are the following:

tas         = (char ***)realloc(tas,sizeof(char **)*(i+1));
tas[i]      = (char **)calloc(2,sizeof(char *));
tas[i][0]   = (char *)calloc(lenKey+1,sizeof(char));
tas[i][1]   = (char *)calloc(lenValue+1,sizeof(char));
++i;

With tas beeing the char***.

--------EDIT-------

Piece by piece I compiled an answer and i am posting the solution i found to the problem here.


Solution

  • This is not so hard, you just need to keep your head clear.

    First off, keep the general pattern in mind: To allocate an array of n elements of type T, use:

    T * p = malloc(n * sizeof(T));
    

    Then initialize the values p[i] for i in the range [0, n), then de-initialize the elements when you're done, if necessary, and then release the array allocation with:

    free(p);
    

    Now just do this recursively for your array of arrays of strings, bearing in mind that a string is an array of characters, m rows of n columns of strings:

    // allocate the table (the row pointers)
    char *** tas = malloc(m * sizeof(char**));
    
    for (size_t i = 0; i != m; ++i)
    {
        // allocate each row (the row cells)
        tas[i] = malloc(n * sizeof(char*));
        for (size_t j = 0; j != n; ++j)
        {
            // initialize the row cell by allocating the string
            tas[i][j] = /* allocate string */
        }
    }
    

    And on the way back, to free everything:

    for (size_t i = 0; i != m; ++i)
    {
        for (size_t j = 0; j != n; ++j)
        {
            free(tas[i][j]);  // free the string
        }
    
        free(tas[i]);         // free the row
    }
    
    free(tas);                // free the table