简体   繁体   English

VALGRIND对大小8的无效读取,链接列表,释放节点

[英]VALGRIND invalid read of size 8, linked list, freeing nodes

I'm trying to identify the reason why Valgrind is complaining. 我正在尝试找出Valgrind抱怨的原因。

If somebody could give me a hint so that I can understand why my code is generating bad behaviour I would be very grateful. 如果有人可以给我一个提示,以便我能理解为什么我的代码会产生不良行为,我将不胜感激。

I've created an array of structures. 我创建了一个结构数组。 Each entry is the beginning of a linked list made out of structs. 每个条目都是由结构组成的链表的开头。 Now I'm at the Point where I want to free the elements of each linked list of that array of structs. 现在,我要释放该结构数组的每个链接列表中的元素。

But Valgrind is saying: 但是瓦尔格朗德说:

==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)

That seems to be the faulty function 那似乎是错误的功能

    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: }

The structures look like this: 结构如下所示:

  16: struct node {
  17:   char *volume;
  18:   struct node *next;
  19:   };

I'm looking forward for your help. 我期待着您的帮助。

This is a fairly typical coding style which works until (a) you use valgrind or (b) actually have a system where another thread can get hold of your memory when you've freed it. 这是一种相当典型的编码样式,在(a)您使用valgrind或(b)实际上有一个系统中,另一个线程可以在释放它后保留您的内存,该代码风格才能起作用。

for(; (*p).next != NULL; p=(*p).next)
{
     free((*p).next);
}

As you go through that loop, you get hold of p and then you free the thing it is pointing to. 当您经历该循环时,您将拥有p,然后释放其指向的对象。

free(p->next); //p->next now points to freed memory

Then you get hold of the thing you've just freed 然后,您掌握了刚刚释放的东西

p = p->next; //p now points to freed memory

and then you tree to free what that is pointing to 然后您就可以释放指向的内容

free(p->next); //Trying to access freed memory

Then you have to have extra code to free the first element in the list because you can't have freed it in that loop. 然后,您必须具有额外的代码才能释放列表中的第一个元素,因为您无法在该循环中释放它。

Note that Tom Tanner gave the correct diagnosis in his answer. 请注意, 汤姆·坦纳Tom Tanner )在回答中给出了正确的诊断 Please give him the credit for that. 为此请给他功劳。

Please use the -> arrow operator instead of (*p).next ; 请使用->箭头运算符代替(*p).next it was invented for a good reason. 它是有充分理由发明的。

Your freeing code is currently: 您的释放代码当前为:

struct node *p = &conti[i];
if((*p).next != NULL)
{
    for(; (*p).next != NULL; p=(*p).next)
    {
        free((*p).next);
    }
}

Note that the loop repeats the test made in the if condition in your code; 请注意,循环重复在代码的if条件下进行的测试; that's unnecessary and you can simply remove the if code, but not the loop inside it, of course. 这是不必要的,当然,您可以简单地删除if代码,但不能删除其中的循环。

The code should take care to avoid accessing freed memory. 该代码应注意避免访问释放的内存。 You can do that with a more or less standard technique which preserves the next pointer value before the memory is free: 您可以使用或多或少的标准技术来做到这一点,该技术会在内存释放之前保留next指针值:

struct node *p = &conti[i]->next;
while (p != NULL)
{
    struct node *next = p->next;
    free(p);
    p = next;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM