这是经过编辑的代码:
我有一个二维堆栈,比如
#define push(s,ele) s.list[++(s.last)]=ele
typedef struct vp {
short int v1,v2;
}VPTYPE;
typedef struct VPLIST{
int last;
VPPTR *list;
}VPLISTTYPE,*VPLISTPTR ;
VPLISTPTR v1v2;
v1v2=(VPLISTPTR)malloc(sizeof(VPLISTTYPE)*nof);
a=0;
while(a<100)
{ //allocation part
for(i=0;i< nof;i++)
{
v1v2[i].list=(VPPTR *)malloc(20*(sizeof(VPPTR)));
for(i2=0;i2< 10;i2++) //please note that I am not filling the array completely, in the actual code the value 10 is dependent on certain factors, which I am omitting for the sake of simplicty
{
v=(VPTYPE *)malloc(sizeof(VPTYPE));
push(v1v2[i],v);
v1v2[i]->v1=1;v1v2[i]->v2=2;
}
}
// some algorithm goes on here which accesses these values in the stack
// free memory part
for(i=0;i< nof;i++)
{
for(i2=0;i2<= (v1v2[i2].last);i2++)
{
free(v1v2[i2].list[i]);
}
}
a++;
}
当我以这种方式释放内存时会出现内存泄漏。请让我知道我哪里出错了。
非常感谢。
答案 0 :(得分:2)
除非我误解了代码,看起来就像你push
,因为你使用预增量,.last
字段实际上保存了最后一个东西的索引,而不是多少个被推了。但是,当你循环到free
时,你会在 less 而不是小于或等于的情况下循环。
答案 1 :(得分:2)
您没有在显示的代码中初始化已分配的内存。通常,您会获得malloc()
分配的非零垃圾。如果您需要归零内存,请使用calloc()
。
JCooper的答案也确定了问题。
Muggen的评论也指出了问题。
您正在释放堆栈中的项目,但不是整个堆栈。这应该在“for (i2 = 0; ...)
”循环内部完成,但在“for (k2 = 0; ...)
”循环之后完成。
总的来说,这些都会导致一场小小的灾难。
代码编辑后......
typedef VPTYPE *VPPTR;
。在您的可用内存循环中,在调用free()
时,您已经颠倒了i
和i2
的角色:
free(v1v2[i2].list[i]); // Yours
free(v1v2[i].list[i2]); // Mine
v1v2[i]->v1=1;v1v2[i]->v2=2;
)是假的。以下代码编译清理并运行干净:
$ cc -Wall -Wextra -g -O3 -std=c99 x.c -o x
$ valgrind ./x
==16593== Memcheck, a memory error detector.
==16593== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==16593== Using LibVEX rev 1658, a library for dynamic binary translation.
==16593== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==16593== Using valgrind-3.2.1, a dynamic binary instrumentation framework.
==16593== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==16593== For more details, rerun with: -v
==16593==
==16593==
==16593== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==16593== malloc/free: in use at exit: 0 bytes in 0 blocks.
==16593== malloc/free: 2,201 allocs, 2,201 frees, 40,032 bytes allocated.
==16593== For counts of detected errors, rerun with: -v
==16593== All heap blocks were freed -- no leaks are possible.
$
#include <stdlib.h>
#include <stdio.h>
#define push(s, ele) ((s).list[((s).last)++] = (ele))
typedef struct vp
{
short v1;
short v2;
} VPTYPE;
typedef struct VPLIST
{
int last;
VPTYPE **list;
} VPLISTTYPE;
enum { nof = 2 };
int main(void)
{
VPLISTTYPE *v1v2 = (VPLISTTYPE *)malloc(sizeof(*v1v2) * nof);
for (int i = 0; i < nof; i++)
v1v2[i].last = 0;
for (int a = 0; a < 100; a++)
{
//allocation part
for (int i = 0; i < nof; i++)
{
v1v2[i].list = (VPTYPE **)malloc(20 * sizeof(*v1v2[i].list));
for (int i2 = 0; i2 < 10; i2++)
{
VPTYPE *v = (VPTYPE *)malloc(sizeof(*v));
v->v1 = 1;
v->v2 = 2;
push(v1v2[i], v);
}
}
// free memory part
for (int i = 0; i < nof; i++)
{
for (int i2 = 0; i2 < (v1v2[i].last); i2++)
{
free(v1v2[i].list[i2]);
}
free(v1v2[i].list);
v1v2[i].list = 0;
v1v2[i].last = 0;
}
}
free(v1v2);
return 0;
}
这段代码使用一个较少级别的间接 - 因此一个较少级别的内存分配 - 并且编译和运行同样干净。
#include <stdlib.h>
#include <stdio.h>
#define push(s, ele) ((s).list[((s).last)++] = (ele))
typedef struct vp
{
short v1;
short v2;
} VPTYPE;
typedef struct VPLIST
{
int last;
VPTYPE *list;
} VPLISTTYPE;
enum { nof = 2 };
int main(void)
{
VPLISTTYPE *v1v2 = (VPLISTTYPE *)malloc(sizeof(*v1v2) * nof);
for (int i = 0; i < nof; i++)
v1v2[i].last = 0;
for (int a = 0; a < 100; a++)
{
//allocation part
for (int i = 0; i < nof; i++)
{
v1v2[i].list = (VPTYPE *)malloc(20 * sizeof(*v1v2[i].list));
for (int i2 = 0; i2 < 10; i2++)
{
VPTYPE v;
v.v1 = 1;
v.v2 = 2;
push(v1v2[i], v);
}
}
// free memory part
for (int i = 0; i < nof; i++)
{
free(v1v2[i].list);
v1v2[i].list = 0;
v1v2[i].last = 0;
}
}
free(v1v2);
return 0;
}