【发布时间】:2020-07-04 12:38:08
【问题描述】:
所以我有这个函数来分配和初始化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: %zu\n", size);
toks_groups[size] = NULL;
size--;
}
return (toks_groups);
}
它工作正常,但是当我在 Valgrind 中运行我的程序(这是一个极简的 shell)时,
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 的指针,而且我在填充时没有任何问题或错误(嗯,不是我检测到的),在程序中操作和读取那些链表数组。我假设我对内存做了一些奇怪的事情,但我不知道在哪里。
【问题讨论】:
-
size +1在对malloc的调用中必须是(size+1)。 -
什么是
toks_groups?它与t_tokens有什么关系?虽然@DYZ 提到的问题可能是导致 Valgrind 错误的原因,但请尝试创建一个minimal reproducible example 以向我们展示。 -
在不相关的注释中,您的循环
while (size + 1)非常奇怪。为什么不简单地使用for (size_t i = 0; i < size + 1; ++i),这是用于迭代一系列值(如数组索引)的最常见和标准的循环类型。 -
@Someprogrammerdude 我以后会做的。此外,这是一个学校项目,出于某些原因(我不明白),我们不允许使用“for”循环。
-
@Zest 不允许
for循环似乎是一些教师似乎喜欢的那些奇怪且通常是任意的限制之一,尤其是当它与作业本身无关时。无论如何,for看起来像for (init; cond; increment) { body }可以翻译成init; while (cond) { body; increment }
标签: c memory valgrind allocation