I need to pass an array of structs to a function and it is my understanding that I have to allocate memory for the whole array of structs, as well as for each individual struct member in every struct inside the array.
The way I have done it results in an invalid write error from valgrind (caused in the second line inside function read_file). What is wrong?
typedef struct test
{
char *string1;
int num1;
int num2;
char *string2;
} Test;
static void read_file(Test *test)
{
test = (Test *)calloc(16, sizeof(test));
test[0].string1 = (char *)calloc(strlen("hello") + 1, sizeof(char));
}
int main(void)
{
int i = 0;
Test test[16];
for (i = 0; i < 16; i++)
{
memset(&test[i], 0, sizeof(test[i]));
test[i] = (Test) { "", 0, 0, "" };
}
read_file(test);
return 0;
}
PS: I know that I have to free the allocated memory, but first I want to get the above code working.
Test *test
The test
variable inside read_file
function is a pointer
to the Test struct.
sizeof(test)
This is equal to the sizeof of a pointer.
test = (Test *)calloc(16, sizeof(test));
This allocates memory for 16 pointer to Test
structure. This does not allocate memory for 16 structures, only for pointers to them.
test[0].string1 =
is invalid and undefined behavior happens. As sizeof(test)
is way smaller then sizeof(Test)
, there is not enough memory to access test0[].string1
. So this accesses the memory "out of bounds" and this accesses invalid / not allocated memory region. As you try to write to it (you are doing an assigment) the expresssion is invalid and undefined behavior happens. Valgrind correctly detects that as "write error" - you try to write to memory you don't own.