I simplified a part of my project to solve this specific problem I have (invalid write of size 4/segmentation fault)

Viewed 21

A step by step compiler says "Invalid write of size 4", while in general it's a segmentation fault. I don't understand how to solve this. I have been fidgeting with this for the past few hours. What am I missing?

typedef struct Person{
  int age;
  char name[6]
} Person;

fun(Person **parray){
  *parray = realloc(*parray, 6 * (sizeof(Person)));
    for(int i = 0; i < 6; ++i){
      strcpy (parray[i]->name, "John");
      parray[i]->age = 15;
    }
}

int main() {
  Person *parray;
  
  parray = calloc(0, sizeof(Person));
  
  fun(&parray);
  
  return 0;
}
1 Answers

I don't understand how to solve this.

The first step should be to enable compiler warnings, and fix all the bugs the compiler tells you about. If you are using gcc, turn on -Wall -Wextra flags.

Now, the bug is in that parray[i] inside fun() is not the correct expression -- it treats parray as pointer to an array, when in fact parray points to a single variable (of the same name) in main().

You can fix this by using the correct expression: (*parray)[i].

A better fix is to avoid the double pointer altogether, e.g.:

#include <stdlib.h>
#include <string.h>

typedef struct Person{
  int age;
  char name[6]
} Person;

Person *fun(Person *parray){
  Person *result = realloc(parray, 6 * (sizeof(Person)));
  for(int i = 0; i < 6; ++i){
    strcpy(result[i].name, "John");
    result[i].age = 15;
  }
  return result;
}

int main()
{
  Person *parray = calloc(0, sizeof(Person));
  parray = fun(parray);

  free(parray);
  return 0;
}

If you insist on passing a double-pointer into fun() and updating it inside, you can do that, while still minimizing the use of the double-pointer, like so:

void fun(Person **parray){
  Person *p = *parray = realloc(*parray, 6 * (sizeof(Person)));
  for(int i = 0; i < 6; ++i){
    strcpy(p[i].name, "John");
    p[i].age = 15;
  }
}
Related