Search code examples
cdynamic-memory-allocationclion

C memory allocationd


void mem_init(int n) {
    struct A{
        int thing1;
        double thing2;
    };
    arr_A= malloc(sizeof(struct A)*n);

    for(int i=0; i<n; i++){
        arr_A[i] = malloc(sizeof(struct A));
        arr_A[i]->thing1 =1;
        arr_A[i]->thing2 =2;
    }
}


void mem_free() {
    free(A);
}

I just set the struct array as global variable and solved this problem. thank you so much.


Solution

  • I want to have a array of struct A, so I declared the array in function 'mem_init'.

    this is not what you did because struct A *arr_A[n]; is an array of pointers tostruct A.

    An array of struct A can be

    struct A arr_A[n]; // variable length array 
    

    or

    struct A * arr_A = malloc(n * sizeof(struct A));
    

    Of course having an array of struct A rather that pointer to the loop is modified :

    for(int i=0; i<n; i++){
       arr_A[i].thing1 =1;
       arr_A[i].thing2 =2;
    }
    

    now I want to make a function to free the memory of 'arr_A'

    if arr_A is your array of pointer you can do (supposing the definition of A known out of mem_init) :

    void mem_free(struct A ** arr_A, int n)
    {
       for(int i=0; i<n; i++)
         free(arr_A[i]);
    }
    

    else (the function is not really useful and free can be used directly rather than to define and call mem_free) :

    void mem_free(struct A *arr_A)
    {
       free(arr_A);
    }
    

    Out of that currently the call of mem_free can only be done in mem_init because only it knows the array, do you really want that ? If not mem_init can return the address of the array, using your array of pointers a solution is :

    #include <stdlib.h>
    
    struct A {
      int thing1;
      double thing2;
    };
    
    struct A ** mem_init(int n) {
      struct A ** arr_A = malloc(n * sizeof(struct A *));
      
      for(int i=0; i<n; i++){
        arr_A[i] = malloc(sizeof(struct A));
        arr_A[i]->thing1 =1;
        arr_A[i]->thing2 =2;
      }
      
      return arr_A;
    }
    
    void mem_free(struct A ** arr_A, int n)
    {
      for(int i=0; i<n; i++)
        free(arr_A[i]);
      free(arr_A);
    }
    
    int main()
    {
      const int nelt = 10;
      struct A ** arr_A = mem_init(nelt);
      
      mem_free(arr_A, nelt);
      return 0;
    }
    

    Note I moved the definition of A outside, and the array is not anymore a local VLA to mem_init to be able to use it after the execution of mem_init

    Compilation and execution:

    pi@raspberrypi:/tmp $ gcc -Wall c.c
    pi@raspberrypi:/tmp $ ./a.out
    pi@raspberrypi:/tmp $ valgrind ./a.out
    ==12721== Memcheck, a memory error detector
    ==12721== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==12721== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
    ==12721== Command: ./a.out
    ==12721== 
    ==12721== 
    ==12721== HEAP SUMMARY:
    ==12721==     in use at exit: 0 bytes in 0 blocks
    ==12721==   total heap usage: 11 allocs, 11 frees, 200 bytes allocated
    ==12721== 
    ==12721== All heap blocks were freed -- no leaks are possible
    ==12721== 
    ==12721== For lists of detected and suppressed errors, rerun with: -s
    ==12721== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    pi@raspberrypi:/tmp $