所以我有一个函数,它将为NULL
分配并初始化一个链表数组。实际上,我希望这个函数返回一个NULL
指针数组,以便以后可以用链表填充它。
static t_tokens **init_tokens_groups(size_t size)
{
t_tokens **toks_groups;
if (!(toks_groups = malloc(sizeof(toks_groups) * size + 1)))
exit(EXIT_FAILURE);
while (size + 1)
{
printf("size: %zun", size);
toks_groups[size] = NULL;
size--;
}
return (toks_groups);
}
它工作得很好,但当我在Valgrind中运行我的程序(这是一个极简主义的外壳(时,
valgrind --track-origins=yes ./mysh
我遇到了这个:
==4914== Invalid write of size 8
==4914== at 0x10AD6B: init_tokens_groups (tokens_split.c:39)
==4914== by 0x10AE06: split_tokens (tokens_split.c:68)
==4914== by 0x1093D9: prompt_loop (sh21.c:38)
==4914== by 0x10944A: main (sh21.c:57)
==4914== Address 0x4a508f8 is 8 bytes inside a block of size 9 alloc'd
==4914== at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4914== by 0x10AD42: init_tokens_groups (tokens_split.c:35)
==4914== by 0x10AE06: split_tokens (tokens_split.c:68)
==4914== by 0x1093D9: prompt_loop (sh21.c:38)
==4914== by 0x10944A: main (sh21.c:57)
==4914==
==4914== Invalid write of size 8
==4914== at 0x10AD6B: init_tokens_groups (tokens_split.c:39)
==4914== by 0x10AE06: split_tokens (tokens_split.c:68)
==4914== by 0x109369: dispatch (sh21.c:19)
==4914== by 0x1093F6: prompt_loop (sh21.c:42)
==4914== by 0x10944A: main (sh21.c:57)
==4914== Address 0x4a509f8 is 8 bytes inside a block of size 9 alloc'd
==4914== at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4914== by 0x10AD42: init_tokens_groups (tokens_split.c:35)
==4914== by 0x10AE06: split_tokens (tokens_split.c:68)
==4914== by 0x109369: dispatch (sh21.c:19)
==4914== by 0x1093F6: prompt_loop (sh21.c:42)
==4914== by 0x10944A: main (sh21.c:57)
我真的不明白它是从哪里来的,因为我只是在这个阶段初始化指向NULL
的指针,在填充、操作和读取程序中的链表数组时,我没有遇到任何问题或错误(好吧,我没有检测到(。我想我是在用记忆做一些奇怪的事情,但我不知道在哪里。
这:
toks_groups = malloc(sizeof(toks_groups) * size + 1))
是错误的,并在以后第一次执行toks_groups[size] = NULL;
(位于分配的区域之外(时导致问题。Valgrind告诉您无效写入为8字节,因为系统上的指针大小为8字节。
如果要分配size + 1
元素,则应将表达式放在括号中。你在做sizeof(toks_groups)
这个事实也很奇怪,没有多大意义。你可能想做的是:
toks_groups = malloc(sizeof(*toks_groups) * (size + 1)))
如果只想分配size
元素(而不是size + 1
(,则从malloc()
中删除+ 1
并更改while (...)
条件。您也根本不需要while
,如果您想将所有内容初始化为NULL
,您可以使用calloc()
而不是malloc()
。
此外,作为经验法则:
- 使用有意义的名称。当某个东西显然不是一个大小,而只是一些元素时,调用
size
是令人困惑的 - 使用正确的代码构造。使用
while
循环对一系列值进行迭代实际上是违反直觉的,很容易导致错误
上述代码的更好版本如下:
static t_tokens **init_tokens_groups(size_t n)
{
t_tokens **toks_groups;
if (!(toks_groups = calloc(sizeof(*toks_groups) * (n + 1))))
exit(EXIT_FAILURE);
return toks_groups;
}
我仍然不确定你是否真的需要额外的元素,但你应该知道。