释放二维堆栈数组

时间:2011-04-05 19:16:43

标签: c

这是经过编辑的代码:

我有一个二维堆栈,比如

#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++;
}

当我以这种方式释放内存时会出现内存泄漏。请让我知道我哪里出错了。

非常感谢。

2 个答案:

答案 0 :(得分:2)

除非我误解了代码,看起来就像你push,因为你使用预增量,.last字段实际上保存了最后一个东西的索引,而不是多少个被推了。但是,当你循环到free时,你会在 less 而不是小于或等于的情况下循环。

答案 1 :(得分:2)

  • 您没有在显示的代码中初始化已分配的内存。通常,您会获得malloc()分配的非零垃圾。如果您需要归零内存,请使用calloc()

  • JCooper的答案也确定了问题。

  • Muggen的评论也指出了问题。

  • 您正在释放堆栈中的项目,但不是整个堆栈。这应该在“for (i2 = 0; ...)”循环内部完成,但在“for (k2 = 0; ...)”循环之后完成。

总的来说,这些都会导致一场小小的灾难。


代码编辑后......

  • VPPTR类型未定义,但可能是'typedef VPTYPE *VPPTR;
  • 在struct VPLIST中,你有一个指向VPPTR的指针 - 另一个不信任这种指针typedef的理由。你几乎肯定打算在那里有一个简单的VPPTR。但是,其他代码确实假设您需要一个指向指针的数组,因此它是自洽的(直到某一点)。
  • 此问题传播到内存分配代码中。
  • 在您的可用内存循环中,在调用free()时,您已经颠倒了ii2的角色:

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