Освобождение двумерного массива стека - PullRequest
0 голосов
/ 05 апреля 2011

Это отредактированный код:

У меня есть двумерный стек, как

#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 ]

2 голосов
/ 05 апреля 2011
  • Вы не инициализируете выделенную память в показанном вами коде. В общем случае вы получаете ненулевой мусор, выделенный malloc(). Если вам нужна нулевая память, используйте calloc().

  • Существует также проблема, выявленная в ответе JCooper .

  • Существует также проблема, указанная в комментарии Muggen .

  • Вы освобождаете предметы в стеке, но не в стопках в целом. Это должно быть сделано внутри цикла for (i2 = 0; ...), но после цикла for (k2 = 0; ...).

В совокупности это составляет небольшую катастрофу.


После редактирования кода ...

  • Тип VPPTR не определен, но, предположительно, предполагается, что он равен typedef VPTYPE *VPPTR;.
  • В структуре VPLIST у вас есть указатель на VPPTR - еще одна причина не доверять таким типам указателей. Вы почти наверняка намеревались иметь простой 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;
}
2 голосов
/ 05 апреля 2011

Если я неправильно понимаю код, похоже, что когда вы push, потому что вы используете предварительное увеличение, поле .last фактически содержит индекс последней вещи, а не счетчик того, сколько было нажато.Однако, когда вы перебираете их free, вы зацикливаетесь, пока меньше , чем в прошлом, не меньше или равно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...