为什么我得到这个无效的读取大小 8
Why do i get this Invalid read size of 8
为什么我得到一个 Invalid read of size 8
我的目标是将一个整数数组传递给一个函数,该函数将 return 指向链表中最后一个 Item
的指针,并将填充 Item
的数组指针和创建的每个项目的指针
一切正常,编译没有显示任何错误,运行程序也没有显示任何错误,但是当我使用 valgrind
时,我在下面的 valgrind 输出中得到错误
typedef struct Item
{
int num ;
struct Item *next;
}Item;
Item * create_list(int * arr, int len, Item ** lst)
{
Item * tmpItem = malloc(sizeof(Item));
for (int i=0; i < len; i++)
{
lst[i] = tmpItem;
tmpItem->num = arr[i];
if ( i+1!=len )
{
tmpItem->next = malloc(sizeof(Item));
tmpItem = tmpItem->next;
}
else
tmpItem->next = NULL;
}
return tmpItem;
}
void free_lst(Item ** lst, int len)
{
for (int i =0; i < len; i++)
{
free(lst[i]);
}
}
int main()
{
int arr[] = {1,2,3,4,5};
Item * items[sizeof(arr)/sizeof(int)];
Item * tmp = create_list(arr, sizeof(arr)/sizeof(int), items);
free_lst(items, sizeof(arr)/sizeof(int));
printf('%p\n',tmp->next);
}
valgrind 输出
==12169== Invalid read of size 8
==12169== at 0x109270: main (main.c:26)
==12169== Address 0x4a59228 is 8 bytes inside a block of size 16 free'd
==12169== at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12169== by 0x10939D: free_lst (list.c:45)
==12169== by 0x10926B: main (main.c:24)
==12169== Block was alloc'd at
==12169== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12169== by 0x10931C: create_list (list.c:24)
==12169== by 0x109209: main (main.c:13)
==12169==
我不明白为什么会出现这个错误,但我猜这是因为链表中的最后一个元素有一个空指针,这导致最后一个元素的长度为 8 个字节而不是 16 个字节
这里有两个主要错误:
printf('%p'...
而不是 printf("%p"...
在 free_lst()
中释放它后,您尝试 printf()
tmp->next
。这意味着您已经释放了这个堆块,但您仍在尝试从中读取。这就是 valgrind 抛出错误的原因。
一些问题
缺少一个必需项headers。
typedef struct Item
Item * create_list(int * arr, int len, Item ** lst)
前两个参数是必需的,但最后一个未使用。在函数本身中,前向以一种令人困惑的方式声明指针,并且不适用于空列表。这可以简化。
void free_lst(struct Item ** lst, int len)
这会将列表作为数组释放。这没有意义,因为有人将其转换为 linked-list.
int main()
参见 What's the correct declaration of main()?。
Item * items[sizeof(arr)/sizeof(int)];
为什么需要 array of pointer to Item?
free_lst(items, sizeof(arr)/sizeof(int));
一个正在释放尚未初始化的元素数组。我认为您从 valgrind
看到了这种行为,因为 free
在未初始化的内存上被调用。
printf('%p\n',tmp->next);
看到when should I use single quotes了吗?假设列表不为空并打印第二个元素?
意图
一个人正在尝试 推送 linked-list 上的一个项目,这是一种高效的操作,但代码不必要地复杂。此外,当压入一个动态分配的 object 时,pop 释放 object 是有意义的。我已经通过错误检查(假设 POSIX-like 合规性)和上面列出的更改修改了一个代码。
#include <stdlib.h>
#include <stdio.h>
struct Item
{
int num ;
struct Item *next;
};
int main(void)
{
int arr[] = {1,2,3,4,5};
struct Item * head = 0, *cursor;
/* `size_t` stddef, included by stdlib and stdio */
size_t i = sizeof arr / sizeof *arr;
int success = EXIT_SUCCESS; /* stdlib */
while(i) { /* Push backwards. */
struct Item *tmp;
if(!(tmp = malloc(sizeof *tmp))) goto catch; /* stdlib */
tmp->num = arr[--i];
tmp->next = head;
head = tmp;
}
for(cursor = head; cursor; cursor = cursor->next)
printf("%d\n", cursor->num); /* stdio */
goto finally;
catch:
success = EXIT_FAILURE; /* stdlib */
perror("to list"); /* stdio */
finally:
while(head) { /* Pop off linked-list. */
struct Item *const prev = head;
head = head->next;
free(prev); /* stdlib */
}
return success;
}
为什么我得到一个 Invalid read of size 8
我的目标是将一个整数数组传递给一个函数,该函数将 return 指向链表中最后一个 Item
的指针,并将填充 Item
的数组指针和创建的每个项目的指针
一切正常,编译没有显示任何错误,运行程序也没有显示任何错误,但是当我使用 valgrind
时,我在下面的 valgrind 输出中得到错误
typedef struct Item
{
int num ;
struct Item *next;
}Item;
Item * create_list(int * arr, int len, Item ** lst)
{
Item * tmpItem = malloc(sizeof(Item));
for (int i=0; i < len; i++)
{
lst[i] = tmpItem;
tmpItem->num = arr[i];
if ( i+1!=len )
{
tmpItem->next = malloc(sizeof(Item));
tmpItem = tmpItem->next;
}
else
tmpItem->next = NULL;
}
return tmpItem;
}
void free_lst(Item ** lst, int len)
{
for (int i =0; i < len; i++)
{
free(lst[i]);
}
}
int main()
{
int arr[] = {1,2,3,4,5};
Item * items[sizeof(arr)/sizeof(int)];
Item * tmp = create_list(arr, sizeof(arr)/sizeof(int), items);
free_lst(items, sizeof(arr)/sizeof(int));
printf('%p\n',tmp->next);
}
valgrind 输出
==12169== Invalid read of size 8
==12169== at 0x109270: main (main.c:26)
==12169== Address 0x4a59228 is 8 bytes inside a block of size 16 free'd
==12169== at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12169== by 0x10939D: free_lst (list.c:45)
==12169== by 0x10926B: main (main.c:24)
==12169== Block was alloc'd at
==12169== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==12169== by 0x10931C: create_list (list.c:24)
==12169== by 0x109209: main (main.c:13)
==12169==
我不明白为什么会出现这个错误,但我猜这是因为链表中的最后一个元素有一个空指针,这导致最后一个元素的长度为 8 个字节而不是 16 个字节
这里有两个主要错误:
printf('%p'...
而不是printf("%p"...
在
free_lst()
中释放它后,您尝试printf()
tmp->next
。这意味着您已经释放了这个堆块,但您仍在尝试从中读取。这就是 valgrind 抛出错误的原因。
一些问题
缺少一个必需项headers。
typedef struct Item
Item * create_list(int * arr, int len, Item ** lst)
前两个参数是必需的,但最后一个未使用。在函数本身中,前向以一种令人困惑的方式声明指针,并且不适用于空列表。这可以简化。
void free_lst(struct Item ** lst, int len)
这会将列表作为数组释放。这没有意义,因为有人将其转换为 linked-list.
int main()
参见 What's the correct declaration of main()?。
Item * items[sizeof(arr)/sizeof(int)];
为什么需要 array of pointer to Item?
free_lst(items, sizeof(arr)/sizeof(int));
一个正在释放尚未初始化的元素数组。我认为您从 valgrind
看到了这种行为,因为 free
在未初始化的内存上被调用。
printf('%p\n',tmp->next);
看到when should I use single quotes了吗?假设列表不为空并打印第二个元素?
意图
一个人正在尝试 推送 linked-list 上的一个项目,这是一种高效的操作,但代码不必要地复杂。此外,当压入一个动态分配的 object 时,pop 释放 object 是有意义的。我已经通过错误检查(假设 POSIX-like 合规性)和上面列出的更改修改了一个代码。
#include <stdlib.h>
#include <stdio.h>
struct Item
{
int num ;
struct Item *next;
};
int main(void)
{
int arr[] = {1,2,3,4,5};
struct Item * head = 0, *cursor;
/* `size_t` stddef, included by stdlib and stdio */
size_t i = sizeof arr / sizeof *arr;
int success = EXIT_SUCCESS; /* stdlib */
while(i) { /* Push backwards. */
struct Item *tmp;
if(!(tmp = malloc(sizeof *tmp))) goto catch; /* stdlib */
tmp->num = arr[--i];
tmp->next = head;
head = tmp;
}
for(cursor = head; cursor; cursor = cursor->next)
printf("%d\n", cursor->num); /* stdio */
goto finally;
catch:
success = EXIT_FAILURE; /* stdlib */
perror("to list"); /* stdio */
finally:
while(head) { /* Pop off linked-list. */
struct Item *const prev = head;
head = head->next;
free(prev); /* stdlib */
}
return success;
}