大小为 8 的 VALGRIND 无效读取,链表,释放节点
VALGRIND invalid read of size 8, linked list, freeing nodes
我正在尝试找出 Valgrind 抱怨的原因。
如果有人能给我提示,让我理解为什么我的代码会产生不良行为,我将不胜感激。
我创建了一个结构数组。每个条目都是由结构组成的链表的开头。现在我要释放该结构数组的每个链表的元素。
但是 Valgrind 说:
==15084== Memcheck, a memory error detector
==15084== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==15084== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==15084== Command: /tmp/3RKi4ZeFa74f-a.out tests/16_allPositive output/ausgabe_16_allPositive
==15084==
==15084== Invalid read of size 8
==15084== at 0x402006: reset (1441261801.c:807)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0de8 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084== Invalid read of size 8
==15084== at 0x401FEA: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0d48 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084== Invalid read of size 8
==15084== at 0x401FFA: reset (1441261801.c:807)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0d48 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084==
==15084== HEAP SUMMARY:
==15084== in use at exit: 0 bytes in 0 blocks
==15084== total heap usage: 119 allocs, 119 frees, 7,787 bytes allocated
==15084==
==15084== All heap blocks were freed -- no leaks are possible
==15084==
==15084== For counts of detected and suppressed errors, rerun with: -v
==15084== ERROR SUMMARY: 51 errors from 3 contexts (suppressed: 0 from 0)
这似乎是错误的功能
void reset()
784: {
785: //lösche alle (zeiger)char *arrays der conti structs
786: for(int i = 0; i < zeile1; i++)
787: {
788: struct node *p = &conti[i];
789: if((*p).next != NULL)
790: {
791: for(; (*p).next != NULL; p=(*p).next)
792: {
793: free((*p).volume);
794: }
795: free((*p).volume);
796: }else if ((*p).next == NULL)
797: {
798: free((*p).volume);
799: }
800: }
801: //lösche die listenelemente der jeweiligen container
802: for(int i = 0; i < zeile1; i++)
803: {
804: struct node *p = &conti[i];
805: if((*p).next != NULL)
806: {
807: for(; (*p).next != NULL; p=(*p).next)
808: {
809: free((*p).next);
810: }
811: }
812: }
813: //lösche die (zeiger)input char *arrays
814: for (int j = 0; j < zeile2; j++)
815: {
816: free(input[j].volume);
817: }
818: //lösche die struct arrays
819: free(conti);
820: free(input);
821: }
结构如下所示:
16: struct node {
17: char *volume;
18: struct node *next;
19: };
期待您的帮助。
这是一种相当典型的编码风格,直到 (a) 您使用 valgrind 或 (b) 实际上有一个系统,当您释放内存时,另一个线程可以获取您的内存。
for(; (*p).next != NULL; p=(*p).next)
{
free((*p).next);
}
当你通过那个循环时,你得到 p 然后你释放它指向的东西。
free(p->next); //p->next now points to freed memory
然后你得到你刚刚释放的东西
p = p->next; //p now points to freed memory
然后你树释放指向的东西
free(p->next); //Trying to access freed memory
然后你必须有额外的代码来释放列表中的第一个元素,因为你不能在那个循环中释放它。
注意他的回答中的Tom Tanner gave the 。请为此归功于他。
请使用 ->
箭头运算符代替 (*p).next
;它的发明是有充分理由的。
您当前的释放代码是:
struct node *p = &conti[i];
if((*p).next != NULL)
{
for(; (*p).next != NULL; p=(*p).next)
{
free((*p).next);
}
}
请注意,循环会重复您代码中 if
条件下所做的测试;这是不必要的,您当然可以简单地删除 if
代码,但不能删除其中的循环。
代码应注意避免访问已释放的内存。您可以使用或多或少的标准技术来做到这一点,该技术在内存可用之前保留 next
指针值:
struct node *p = &conti[i]->next;
while (p != NULL)
{
struct node *next = p->next;
free(p);
p = next;
}
我正在尝试找出 Valgrind 抱怨的原因。
如果有人能给我提示,让我理解为什么我的代码会产生不良行为,我将不胜感激。
我创建了一个结构数组。每个条目都是由结构组成的链表的开头。现在我要释放该结构数组的每个链表的元素。
但是 Valgrind 说:
==15084== Memcheck, a memory error detector
==15084== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==15084== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==15084== Command: /tmp/3RKi4ZeFa74f-a.out tests/16_allPositive output/ausgabe_16_allPositive
==15084==
==15084== Invalid read of size 8
==15084== at 0x402006: reset (1441261801.c:807)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0de8 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084== Invalid read of size 8
==15084== at 0x401FEA: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0d48 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084== Invalid read of size 8
==15084== at 0x401FFA: reset (1441261801.c:807)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0d48 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084==
==15084== HEAP SUMMARY:
==15084== in use at exit: 0 bytes in 0 blocks
==15084== total heap usage: 119 allocs, 119 frees, 7,787 bytes allocated
==15084==
==15084== All heap blocks were freed -- no leaks are possible
==15084==
==15084== For counts of detected and suppressed errors, rerun with: -v
==15084== ERROR SUMMARY: 51 errors from 3 contexts (suppressed: 0 from 0)
这似乎是错误的功能
void reset()
784: {
785: //lösche alle (zeiger)char *arrays der conti structs
786: for(int i = 0; i < zeile1; i++)
787: {
788: struct node *p = &conti[i];
789: if((*p).next != NULL)
790: {
791: for(; (*p).next != NULL; p=(*p).next)
792: {
793: free((*p).volume);
794: }
795: free((*p).volume);
796: }else if ((*p).next == NULL)
797: {
798: free((*p).volume);
799: }
800: }
801: //lösche die listenelemente der jeweiligen container
802: for(int i = 0; i < zeile1; i++)
803: {
804: struct node *p = &conti[i];
805: if((*p).next != NULL)
806: {
807: for(; (*p).next != NULL; p=(*p).next)
808: {
809: free((*p).next);
810: }
811: }
812: }
813: //lösche die (zeiger)input char *arrays
814: for (int j = 0; j < zeile2; j++)
815: {
816: free(input[j].volume);
817: }
818: //lösche die struct arrays
819: free(conti);
820: free(input);
821: }
结构如下所示:
16: struct node {
17: char *volume;
18: struct node *next;
19: };
期待您的帮助。
这是一种相当典型的编码风格,直到 (a) 您使用 valgrind 或 (b) 实际上有一个系统,当您释放内存时,另一个线程可以获取您的内存。
for(; (*p).next != NULL; p=(*p).next)
{
free((*p).next);
}
当你通过那个循环时,你得到 p 然后你释放它指向的东西。
free(p->next); //p->next now points to freed memory
然后你得到你刚刚释放的东西
p = p->next; //p now points to freed memory
然后你树释放指向的东西
free(p->next); //Trying to access freed memory
然后你必须有额外的代码来释放列表中的第一个元素,因为你不能在那个循环中释放它。
注意他的回答中的Tom Tanner gave the
请使用 ->
箭头运算符代替 (*p).next
;它的发明是有充分理由的。
您当前的释放代码是:
struct node *p = &conti[i];
if((*p).next != NULL)
{
for(; (*p).next != NULL; p=(*p).next)
{
free((*p).next);
}
}
请注意,循环会重复您代码中 if
条件下所做的测试;这是不必要的,您当然可以简单地删除 if
代码,但不能删除其中的循环。
代码应注意避免访问已释放的内存。您可以使用或多或少的标准技术来做到这一点,该技术在内存可用之前保留 next
指针值:
struct node *p = &conti[i]->next;
while (p != NULL)
{
struct node *next = p->next;
free(p);
p = next;
}