我有一些内存错误,我无法理解它是什么以及为什么发生;这是源文件gentree.c的typedef:typedef struct _ELEMENT* PELEMENT; /* definition that PELEMENT is a pointer to _ELEMENT*/typedef struct _ELEMENT{ pNode obj; /*the id or content of the node*/ PELEMENT* children; /* array of pointers*/ PELEMENT parent; /*pointer*/ int childrenCount; /* number of pointers at "children" array*/} ELEMENT;/* definition of the tree structure */typedef struct _tree{ PELEMENT head; int k; /* the max number of children for each node*/ GetKeyFunction getKeyFunc; CloneFunction cloneFunc; PrintFunction printFunc; DelFunction delFunc;} Tree;这是有问题的代码(来自源文件gentree.c):我正在gentree.c中找到另一个函数来调用此函数,但是错误发生在这里:Result DelAux(PELEMENT head, int key,PTree pStruct ){ PELEMENT saveParent;int i=0, j=0; Result deleted=FAILURE; /*a variable to know if the leaf is successfully deleted*/if(pStruct->getKeyFunc(head->obj)==key) /*if the current node is the wanted node*/ { pStruct->delFunc(head->obj); /*first of all dlete the pointer to the node*/ if(head->parent!=NULL) /*if it's not the root*/ { (head->parent->childrenCount)--; /*decrease the number of the father's children by one */ if((head->parent->childrenCount)==0) /*if that was the last child of its father*/ { saveParent=head->parent; free(head); /*free the pointer to the current node's element in tree*/ head=NULL; /*and make it points to null*/ free(saveParent->children); /*then free the pointer to childrens' array*/ saveParent->children=NULL; /*make the pointer to childrens' array points to null*/ } } else { free(head); /*free the pointer to the current node's element in tree*/ head=NULL; /*and make it points to null*/ } return SUCCESS; } if (head->children==NULL) { return FAILURE; } else /*if the current node is not the wanted node*/ { while(i<pStruct->k && j<head->childrenCount) /*then look for the wanted node it in the children of current node*/ { if(head->children[i]!=NULL) /*if there is some child in this cell*/ { j++; deleted=DelAux(head->children[i], key, pStruct); if(deleted==SUCCESS) /*if succeeded to delete*/ { return SUCCESS; } } i++; } } return FAILURE ; /*if didn't succeed */}/***********************************************************************/这是源文件-partition.c中的函数: typedef struct _OBJ* POBJ; typedef struct _OBJ { double xi; double xf; double yi; double yf; int key; } PART;/************************************************/ int GetKey(pNode e){POBJ p=NULL;p=(POBJ)e;return p->key; /*return the key of the node*/}/************************************************/void Del(pNode e){ POBJ p=NULL;p= (POBJ)e; /*p pointe to the node we want to delete*/free(p); /*free the memory the node catches*/p=NULL; /*make it point to null*/}/************************************************/这是valgrind输出:==24885== Memcheck, a memory error detector==24885== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.==24885== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info==24885== Command: ./partition==24885== Parent PID: 24884==24885==--24885----24885-- Valgrind options:--24885-- -v--24885-- --log-file=log1--24885-- --leak-check=full--24885-- --tool=memcheck--24885-- Contents of /proc/version:--24885-- Linux version 2.6.32-358.14.1.el6.x86_64 (mockbuild@x86- 022.build.eng.bos.redhat.com) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) ) #1 SMP Mon Jun 17 15:54:20 EDT 2013--24885-- Arch and hwcaps: AMD64, amd64-sse3-cx16-avx--24885-- Page sizes: currently 4096, max supported 4096--24885-- Valgrind library directory: /usr/lib64/valgrind--24885-- Reading syms from /u1/004/syoavb/hm3/300028420/partition--24885-- Reading syms from /usr/lib64/valgrind/memcheck-amd64-linux--24885-- object doesn't have a dynamic symbol table--24885-- Reading syms from /lib64/ld-2.12.so--24885-- Scheduler: using generic scheduler lock implementation.--24885-- Reading suppressions file: /usr/lib64/valgrind/default.supp==24885== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-24885-by-syoavb- on-t2.technion.ac.il==24885== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-24885-by-syoavb-on-t2.technion.ac.il==24885== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-24885-by- syoavb-on-t2.technion.ac.il==24885====24885== TO CONTROL THIS PROCESS USING vgdb (which you probably==24885== don't want to do, unless you know exactly what you're doing,==24885== or are doing some strange experiment):==24885== /usr/lib64/valgrind/../../bin/vgdb --pid=24885 ...command...==24885====24885== TO DEBUG THIS PROCESS USING GDB: start GDB like this==24885== /path/to/gdb ./partition==24885== and then give GDB the following command==24885== target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=24885==24885== --pid is optional if only one valgrind process is running==24885==--24885-- REDIR: 0x3fc8217520 (strlen) redirected to 0x38049551 (vgPlain_amd64_linux_REDIR_FOR_strlen)--24885-- Reading syms from /usr/lib64/valgrind/vgpreload_core-amd64-linux.so--24885-- Reading syms from /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so--24885-- REDIR: 0x3fc8217390 (index) redirected to 0x4a07bf0 (index)--24885-- REDIR: 0x3fc8217410 (strcmp) redirected to 0x4a08530 (strcmp)--24885-- Reading syms from /lib64/libc-2.12.so--24885-- REDIR: 0x3fc8684e80 (strcasecmp) redirected to 0x480155c (_vgnU_ifunc_wrapper)--24885-- REDIR: 0x3fc8687140 (strncasecmp) redirected to 0x480155c (_vgnU_ifunc_wrapper)--24885-- REDIR: 0x3fc8682df0 (__GI_strrchr) redirected to 0x4a07a70 (__GI_strrchr)--24885-- REDIR: 0x3fc867a8a0 (malloc) redirected to 0x4a0696c (malloc)--24885-- REDIR: 0x3fc867a4e0 (calloc) redirected to 0x4a056d7 (calloc)--24885-- REDIR: 0x3fc867b6d0 (free) redirected to 0x4a06369 (free)--24885-- REDIR: 0x3fc8683500 (memchr) redirected to 0x4a085d0 (memchr)--24885-- REDIR: 0x3fc8689820 (memcpy) redirected to 0x4a08b20 (memcpy)--24885-- REDIR: 0x3fc8681310 (__GI_strlen) redirected to 0x4a07f70 (__GI_strlen)--24885-- REDIR: 0x3fc868aca0 (strchrnul) redirected to 0x4a09f10 (strchrnul)--24885-- REDIR: 0x3fc86846b0 (mempcpy) redirected to 0x4a09f80 (mempcpy)==24885== Invalid read of size 4==24885== at 0x401FD0: GetKey (partition.c:342)==24885== by 0x40110F: DelAux (gentree.c:447)==24885== by 0x401213: DelAux (gentree.c:488)==24885== by 0x4010D1: TreeDelLeaf (gentree.c:433)==24885== by 0x4008C8: DestroyAux (gentree.c:115)==24885== by 0x400915: DestroyAux (gentree.c:124)==24885== by 0x400865: TreeDestroy (gentree.c:98)==24885== by 0x4019CF: DeletePartition (partition.c:177)==24885== by 0x402142: main (main.c:40)==24885== Address 0x4c23570 is 32 bytes inside a block of size 40 free'd==24885== at 0x4A063F0: free (vg_replace_malloc.c:446)==24885== by 0x401FA9: Del (partition.c:334)==24885== by 0x40112C: DelAux (gentree.c:455)==24885== by 0x401213: DelAux (gentree.c:488)==24885== by 0x4010D1: TreeDelLeaf (gentree.c:433)==24885== by 0x4008C8: DestroyAux (gentree.c:115)==24885== by 0x400915: DestroyAux (gentree.c:124)==24885== by 0x400865: TreeDestroy (gentree.c:98)==24885== by 0x4019CF: DeletePartition (partition.c:177)==24885== by 0x402142: main (main.c:40)==24885====24885====24885== HEAP SUMMARY:==24885== in use at exit: 376 bytes in 11 blocks==24885== total heap usage: 98 allocs, 87 frees, 3,776 bytes allocated==24885====24885== Searching for pointers to 11 not-freed blocks==24885== Checked 129,912 bytes==24885====24885== 376 (64 direct, 312 indirect) bytes in 2 blocks are definitely lost in loss record 3 of 3==24885== at 0x4A0577B: calloc (vg_replace_malloc.c:593)==24885== by 0x400C95: TreeAddLeaf (gentree.c:278)==24885== by 0x401942: RefineCell (partition.c:151)==24885== by 0x4020BB: main (main.c:28)==24885====24885== LEAK SUMMARY:==24885== definitely lost: 64 bytes in 2 blocks==24885== indirectly lost: 312 bytes in 9 blocks==24885== possibly lost: 0 bytes in 0 blocks==24885== still reachable: 0 bytes in 0 blocks==24885== suppressed: 0 bytes in 0 blocks==24885====24885== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)==24885====24885== 1 errors in context 1 of 2:==24885== Invalid read of size 4==24885== at 0x401FD0: GetKey (partition.c:342)==24885== by 0x40110F: DelAux (gentree.c:447)==24885== by 0x401213: DelAux (gentree.c:488)==24885== by 0x4010D1: TreeDelLeaf (gentree.c:433)==24885== by 0x4008C8: DestroyAux (gentree.c:115)==24885== by 0x400915: DestroyAux (gentree.c:124)==24885== by 0x400865: TreeDestroy (gentree.c:98)==24885== by 0x4019CF: DeletePartition (partition.c:177)==24885== by 0x402142: main (main.c:40)==24885== Address 0x4c23570 is 32 bytes inside a block of size 40 free'd==24885== at 0x4A063F0: free (vg_replace_malloc.c:446)==24885== by 0x401FA9: Del (partition.c:334)==24885== by 0x40112C: DelAux (gentree.c:455)==24885== by 0x401213: DelAux (gentree.c:488)==24885== by 0x4010D1: TreeDelLeaf (gentree.c:433)==24885== by 0x4008C8: DestroyAux (gentree.c:115)==24885== by 0x400915: DestroyAux (gentree.c:124)==24885== by 0x400865: TreeDestroy (gentree.c:98)==24885== by 0x4019CF: DeletePartition (partition.c:177)==24885== by 0x402142: main (main.c:40)==24885==--24885----24885-- used_suppression: 4 U1004-ARM-_dl_relocate_object--24885-- used_suppression: 2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a==24885====24885== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)这里到底发生了什么?! 最佳答案 我评论: 请注意,您在GetKey()中的代码显示为:POBJ p=NULL;p=(POBJ)e; 可能更简单:POBJ p = (POBJ)e; (初始化为NULL,然后立即初始化没有任何意义 分配)。同样,在Del中,您无需将NULL分配给 即将超出范围的局部变量。这些是陈词滥调。准确,但不是直接问题的根源。我注意到在传递时,我们在任何地方都没有pNode类型的定义(传递给e的GetKey()类型)。还有许多其他类型也缺少;因此,它不是SSCCE(Short, Self-Contained, Correct Example)。这主要意味着我们不能测试代码(不做过多的工作),但是这并不妨碍我们对代码进行一些观察。我也评论: 在DelAux()中,当您 分配给head,仅影响局部变量(函数 参数),而不是调用函数中的指针。这意味着 您的调用函数可能没有意识到它正在访问的数据 已被释放。然后user2750466问: 您能否解释一下“分配到头”是什么意思,与哪条线有关?据我了解,问题是head->obj已在某个地方释放,因此当我们调用Getkey()时,会出现内存错误。告诉我我是否错了。这将占用太多的空间以致无法理智地进行评论,因此成为了答案。它是否解决了整个问题是一个单独的讨论。我引用的代码在DelAux()中;一个相关的已注释掉的摘录是:Result DelAux(PELEMENT head, int key, PTree pStruct){ PELEMENT saveParent; int i = 0, j = 0; Result deleted = FAILURE; if (pStruct->getKeyFunc(head->obj) == key) { pStruct->delFunc(head->obj); if (head->parent != NULL) { (head->parent->childrenCount)--; if ((head->parent->childrenCount) == 0) { saveParent = head->parent; free(head); head = NULL; // This is (1) free(saveParent->children); saveParent->children = NULL; } } else { free(head); head = NULL; // This is (2) } return SUCCESS; } ...head变量作为值传递给此函数;它是一个指针,但它是DelAux()函数的局部变量。我已经在代码中确定了将NULL分配给head的两个位置,这是没有意义的,因为您只影响局部变量head,而不影响调用函数中的指针(有时,,并在其他情况下根据DelAux()的踪迹。有可能(可能)您需要传递TreeDelLeaf()(或valgrind -它们是同一回事,但我不想掩饰指针,所以我个人不会创建或使用ELEMENT **head typedef ),这样您就可以编写:*head = NULL;它会影响调用代码中的变量。当然,函数的其他地方也会有类似的更改-对PELEMENT *head的每个引用都需要进行检查,并且大多数都需要由PELEMENT替换,否则您将创建本地的head d代替*head使用,但要在调用函数中修改值时除外。现在,行ELEMENT *l_head = *head;可能是对head的(递归调用)—因为我们没有足够的代码(我们再次使用SSCCE),所以我们无法分辨。如果那是对pStruct->delFunc(head->obj);的调用,那么在修改后的函数定义下,它将变为:pStruct->delFunc(&head->obj);这会将指针的地址传递给函数,因此函数可以修改指针(特别是将其设置为NULL),并且调用函数将意识到这一点。如当前所写,被调用函数将其DelAux()的副本设置为NULL,而不会影响DelAux()本身。这是我评论的要点。这是人们学习C语言和构建树结构等常见问题。在SO上有很多类似的问题。鉴于我没有有效的代码(并且我不想看到所有代码的副本;我想...假设从您的代码创建了100行的SSCCE,但是它必须很小,或者较小的文件,并且都放在一个文件中,因为它是如此之小),我真的不愿意进一步标准化。关于c - 内存错误,不知道为什么会发生,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20844194/ 10-11 18:56