【发布时间】:2013-12-30 17:12:26
【问题描述】:
我有一些记忆错误,我无法理解这是什么以及为什么会发生; 以下是来自源文件 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 分配给即将超出范围的局部变量。在DelAux()中,当您分配给head时,您只影响局部变量(函数参数),而不是调用函数中的指针。这意味着您的调用函数可能没有意识到它正在访问的数据已被释放。 -
@Jonathan Leffler 你能解释一下“分配给头”是什么意思,你与哪一行有关?据我了解,问题是 head->obj 已在某处被释放,因此当我们调用 Getkey 时出现内存错误,请告诉我我是否错了。
标签: c memory-management memory-leaks valgrind