expandBig() and expandFriends() do not assign values to the new data.
Looks like at least a problem is name assignment.
friends->name[friends->size] is not assigned a value after expandFriends(friends), so strcpy() fails.
void addFriend(Friends * friends, char * val) {
if(friends->size == friends->cap)
expandFriends(friends);
strcpy(friends->name[friends->size], val);
....
Consider using strdup()
// strcpy(friends->name[friends->size], val);
friends->name[friends->size] = strdup(val);
... and in InitializeFriends()
friend->name[i] = NULL;
Code such as below is tedious to review.
Was the size right? IDK, now have to trudge up to friend, find its type. OK that is Friends. Now look for Friends definition and see member char ** name. OK, now with char ** de-referenced we get char *. That matches codes sizeof(char*), so sizeof(char*) OK.
friend->name = realloc(friend->name, sizeof(char*) * friend->cap);
Save time. Code to the size of the de-referenced pointer, not the type. This is easier to code right, review and maintain.
Was the size right?
Yep, by construction, sizeof *(friend->name) is the right size.
// friend->name = realloc(friend->name, sizeof(char*) * friend->cap);
friend->name = realloc(friend->name, sizeof *(friend->name) * friend->cap);
// People * ret = (People*)calloc(DEFAULT_CAP, sizeof(People));
People * ret = calloc(DEFAULT_CAP, sizeof *ret);
Unclear why code sometimes casts the return from a *alloc() call and sometimes did not. The cast is not needed.
expandBigdo? What doesexpandFriendsdo? Please post an minimal reproducible example. Please post all code in one big code block, so that it is easy to copy it.add2people(People * people, char * val), who are the 2 people added?