我需要将一个结构体数组传递给一个函数,据我了解,我必须为整个结构体数组以及该数组中每个结构体中的每个结构体成员分配内存。
我这样做的方式导致valgrind产生无效的写入错误(在函数read_file的第二行中引起)。怎么了?
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:我知道我必须释放分配的内存,但是首先我想使上面的代码正常工作。
答案 0 :(得分:2)
test
中的main
数组已经为其分配了内存。
然后将其传递到read_file
函数中,因此无需再次为其分配内存。删除此:
test = (Test *)calloc(16, sizeof(test));
顺便说一句,您可能打算在那里sizeof(Test)
(或选择sizeof(*test)
)。 sizeof(test)
与sizeof(Test*)
相同,几乎可以肯定小于sizeof(Test)
。
答案 1 :(得分:0)
Test *test
test
函数中的read_file
变量是Test结构的pointer
。
sizeof(test)
这等于指针的大小。
test = (Test *)calloc(16, sizeof(test));
这将为Test
结构的16个 pointer 分配内存。这不会为16个结构分配内存,而只会为指向它们的指针分配内存。
test[0].string1 =
无效,并且发生未定义的行为。由于sizeof(test)
比sizeof(Test)
小得多,因此没有足够的内存来访问test0[].string1
。因此,这将“超出范围”访问内存,并且将访问无效/未分配的内存区域。当您尝试对其进行写操作(您正在进行分配)时,该表达无效并且发生未定义的行为。 Valgrind正确地将其检测为“写入错误”-您尝试写入您不拥有的内存。