I want to dynamically add new elements to a array of structs. I have added a minimal example that segfaults. I think I have to pass a pointer struct data **arr to the function to reallocate and add new element correctly, but I haven't been able to do it correctly.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct data {
char s[10];
int arr[10];
};
void add_one_element(struct data *arr, int *num_elements)
{
/*increment counter*/
*num_elements +=1;
arr = realloc(arr, *num_elements * sizeof(struct data));
strcpy(arr[*num_elements-1].s, "ABC");
for(int i = 0; i < 10; i++)
arr[*num_elements-1].arr[i] = i;
}
int main()
{
struct data *arr = NULL;
int num_elements = 0;
add_one_element(arr, &num_elements);
printf("arr.s = %s\n", arr[num_elements-1].s);
for(int i = 0; i < 10; i++)
printf("arr[%d].arr[%d] = %d\n", num_elements-1, i, arr[num_elements-1].arr[i]);
free(arr);
return 0;
}
EDIT 1: Tried to correct the problem. This time I get test(91537,0x7fff79532000) malloc: *** error for object 0x7fff5f5c0ad0: pointer being realloc'd was not allocated. Which suggest that the reallocation failed.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct data {
char s[10];
int arr[10];
};
void add_one_element(struct data **arr, int *num_elements)
{
/*increment counter*/
*num_elements +=1;
arr = realloc(arr, *num_elements * sizeof(struct data));
strcpy(arr[*num_elements-1]->s, "ABC");
for(int i = 0; i < 10; i++)
arr[*num_elements]->arr[i] = i;
}
int main()
{
struct data *arr = NULL;
int num_elements = 0;
add_one_element(&arr, &num_elements);
printf("arr.s => %s\n", arr[num_elements-1].s);
for(int i = 0; i < 10; i++)
printf("arr[%d].arr[%d] = %d\n", num_elements-1, i, arr[num_elements-1].arr[i]);
return 0;
}
reallocating the address of a local variable instead ofarrinmain, pass a pointer to pointer:void add_one_element(struct data **arr, int *num_elements)andadd_one_element(&arr, &num_elements);arr = realloc(arr, ...is very bad practice! What ifreallocreturns a null pointer? You loose the array. First thing is to have proper error handling!realloc()can lead to quadratic performance over time, in general, as it has to copy all the previous entries to the new location — in general. The normal technique is to (a) keep a record of the number of allocated entries as well as the number of entries in use, and (b) double the number of allocated entries when you need to allocate more. If, when you're finished adding, there is enough extra allocated space to warrant it, you could use a shrinkingrealloc()to return the unused space. 'Enough' — depends; think 256 bytes or more, perhaps.