Search code examples
carraysmultidimensional-arraydynamic-memory-allocation

Why how do i this error when trying to free an array of strings


I would like to know how to free this array properly so I dont get this next error when i compile the file. The "ooo" are the strings that i stored in the array

ooo
ooo
ooo
ooo

Error in `./a.out': munmap_chunk(): invalid pointer: 0x0000000000400774
Aborted (core dumped)

I am learning C, if someone can tell me how to fix the error and why it happened I would appreciate it thank you.

here is the code:

#include <stdio.h>
#include<stdlib.h>
#define width 5
#define height 10

char** arrayFunction(){

    char** arrayInFunction = malloc(height * sizeof(char*));
    for(int i=0; i < height; i++){
        arrayInFunction[i] = malloc(width * sizeof(char));
    }
    return arrayInFunction;
    
}
int main()
{
    char** array = arrayFunction();
    array[0] = "ooo";
    array[1] = "ooo";
    array[2] = "ooo";
    array[3] = "ooo";

    for(int i=0; i < height; i++){
    printf("%s\n",array[i]);

    }
    
    //free the array created in main
    for(int i=0; i < height; i++){
    free(array[i]);
    }
    free(array);

    return 0;
}

Solution

  • array[0] = "ooo";

    This changes the char * (a pointer to some char) in array[0] to point to the first character of "ooo". It now does no longer point to the memory you just allocated.

    Thus when you attempt to free this memory, you're getting undefined behavior (= crash and error in your case).

    You need to copy the contents of the C string "ooo" to the allocated memory, e.g. using strcpy or (better) strncpy.


    Visualization; before:

    array: [0][1][2][3][4]
            |
            v
           [?][?][?]... (the memory you allocated)
    

    after:

    array: [0][1][2][3][4]
          __|
         |  
         | [?][?][?]... (the memory you allocated, now lost; a memory leak)
         |
         v
       ['o']['o']['o']['\0'] (the C literal, wherever the C compiler saved it)
    

    Other issues:

    #define width 5
    #define height 10
    

    Better use const variables, or even better make these two parameters of the arrayFuntion (which should be named better!).

    array[3] = "ooo";
    
    for(int i=0; i < height; i++)
    

    array[4] is left uninitialized. Accessing it (in the loop) is undefined behavior.

    char** arrayInFunction = malloc(height * sizeof(char*));
    

    Better avoid sizeof(TYPE) when you can, it's safer to use sizeof(EXPRESSION), e.g. for above:

    char** arrayInFunction = malloc(height * sizeof(*arrayInFunction));
    

    Same for the other sizeof expression.

    return 0;
    

    Not necessary in main.