Search code examples
cmultidimensional-arraymallocdynamic-memory-allocationrealloc

Realloc variable sized 2D array passed as parameter - C


First of all I want to apologize if this is a repeated question. But I could not find any answer explaining how to do this correctly with a variable sized array.

Going straight to the code, I've got this:

void f(int[][2]);

int main(void)
{
  int (*obsF)[2] = malloc(sizeof(int)); //I reserve some memory so I can pass 
  f(obsF);                              //the array to f, since I don't know
  free(obsF);                           //its size until later working with f. 
}

void f(int obsF[][2])
{
  obsF = realloc(obsF, sizeof(int[5][2])); //The 5 is just as an example.
  // do stuff with obsF                    //I won't know this number until
}                                          //later in f.

Testing this with valgrind threw that that free(obsF); is an invalid free().

Now, if I do the same but everything in the main function like this:

int main(void)
{
  int (*obsF)[2] = malloc(sizeof(int));
  obsF = realloc(obsF, sizeof(int[5][2]));
  free(obsF);
}

Valgrind tests passed successfully with no errors.

I would like to know why this is happening and how to realloc my 2D array inside function and be able to free it from main correctly.

Any other better approach or solution is well received, as long as I can use obsF as a 2D array inside f and modify it as I wish and then use it in main.

Thanks.-


Solution

  • C passes arguments by value, not by reference. When you pass the obsF pointer to f and reallocate it, you change the value of the obsF parameter in the f function, but the variable in the main function (which determined the parameter's initial value) still holds the old pointer, which has been invalidated by the reallocation.

    To fix this, you can pass a pointer to the obsF variable to f, and dereference that pointer to access the variable:

    void f(int **obsF)
    {
      *obsF = realloc(*obsF, sizeof(int[5][2]));
      // do stuff with obsF
    }
    

    And then call f as:

    int main(void)
    {
      int *obsF = malloc(sizeof(int));
      f(&obsF);
      free(obsF);
    }
    

    This way, the value of the obsF variable inside main will be updated after the call to f and the correct pointer will be freed.