我正在试验链表并尝试创建一个通用的双向链表,它只为每个节点分配一次内存。这意味着节点和节点包含的元素的内存是在同一个 malloc
调用中分配的。
列表本身是一个包含单位大小的结构(使用 sizeof(struct which_is_an_element)
初始化:
struct doubly_linked_list
{
struct dll_node *head, *tail;
size_t elem_size;
};
节点:
struct dll_node
{
struct dll_node *next, *prev;
void *elem;
};
现在,当我尝试插入元素并对其进行初始化时:
static struct dll_node * new_node(
struct doubly_linked_list *l,
void *elem)
{
struct dll_node *n = malloc (
sizeof(struct dll_node) + l->elem_size);
// This line throws valgrind error
memcpy(n + sizeof(struct dll_node), elem, l->elem_size);
n->prev = n->next = NULL;
n->elem = n + sizeof(struct dll_node);
return n;
}
我收到一个 valgrind 错误:
Invalid write of size 8
at 0x4C3217B: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1022) by 0x400705: new_node (doubly_linked_list.c:20)
by 0x400768: dl_list_insert_at_tail (doubly_linked_list.c:30)
by 0x40093F: main (main.c:24)
Address 0x5204280 is 480 bytes inside an unallocated block of size 4,194,112 in arena "client"
- 当分配内存的大小等于
sizeof(struct which_is_an_element) + sizeof(dll_node)
时,真的memcpy
写入未分配 block 吗? - 这些问题是否是由 valgrind 认为分配的内存大小为
sizeof(struct dll_node)
引起的,因为new_node< 中名为
指向数据的函数?n
的指针类型 - 这种方法好吗?我可以为每个元素分配一次内存,还是应该分别为节点和元素分配内存?
- 如果这种方法很好,那么我怎样才能摆脱这个 valgrind 错误?
最佳答案
Does really
memcpy
write inside unallocated block as the size of the allocated memory is equal tosizeof(struct which_is_an_element) + sizeof(dll_node)
?
是的。
执行 memcpy(n + sizeof(struct dll_node), ...
点 sizeof(struct dll_node) * sizeof *n
(等于 sizeof(struct dll_node) * sizeof(struct dll_node)
) 超出 n
指向的字节数。
您可能只想“寻找”sizeof(struct dll_node)
个字节。
这样做,将您的代码更改为:
memcpy((char*)n + sizeof(struct dll_node), ...
或者,因为n
是指向struct dll_node
的指针,就这样
memcpy(n + 1, ...
超越 struct dll_node
。
关于c - Valgrind 错误和每个元素一个分配的通用列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48150621/