Не могу найти 'Определенно потерянная память' в моем коде - PullRequest
1 голос
/ 08 июля 2019

Я пытаюсь создать несколько программ, чтобы правильно подготовиться к тесту, это будет очень скоро.Но на самом деле, после нескольких дней исследований этих кодов, я не могу найти, где на самом деле находятся утечки памяти, о которых сообщает valgrind.

Я попытался освободить почти все указатели, внутренние и внешние.Я попытался освободить некоторые ненужные указатели, но безрезультатно.

Это структура:

typedef struct cop {
   int primo;
   int secondo;
   struct cop *next; 
 } coppia 

Это функции:

coppia *crea_coppia(int x, int y)
{
    coppia *el=malloc(sizeof(coppia));
    el->primo=x;
    el->secondo=y;
    el->next=NULL;
    return el;
}

coppia *crea_coppia_bin(FILE *f)
{
    int buf[2];

    int e = fread(buf,sizeof(int),2,f);

    if(e!=2) return NULL;

    coppia *el = crea_coppia(buf[0],buf[1]);

    if(el==NULL) return NULL;

    return el;
}

coppia *crea_lista(char *nomefile)
{
    FILE *f = fopen(nomefile,"rb");
    coppia *lis=NULL;
    coppia *el=NULL;
    while(true)
    {
        el=crea_coppia_bin(f);
        if(el==NULL)
            break;
        lis=inserisci_coppia(lis,el);
    }
    fclose(f);
    return lis;
}

Выход Valgrind:

==434== HEAP SUMMARY:
==434==     in use at exit: 16 bytes in 1 blocks
==434==   total heap usage: 9 allocs, 8 frees, 8,840 bytes allocated
==434==
==434== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==434==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==434==    by 0x10896D: crea_coppia (provaesame.c:18)
==434==    by 0x1089D1: crea_coppia_bin (provaesame.c:53)
==434==    by 0x108A12: crea_lista (provaesame.c:77)
==434==    by 0x108B6D: main (provaesamemain.c:21)
==434==
==434== LEAK SUMMARY:
==434==    definitely lost: 16 bytes in 1 blocks
==434==    indirectly lost: 0 bytes in 0 blocks
==434==      possibly lost: 0 bytes in 0 blocks
==434==    still reachable: 0 bytes in 0 blocks
==434==         suppressed: 0 bytes in 0 blocks
==434==
==434== For counts of detected and suppressed errors, rerun with: -v
==434== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Это функциякоторый вставляет элемент в список:

coppia *inserisci_coppia(coppia *lis, coppia *el)
{
    if(lis==NULL)
    {
        lis=el;
        return lis;
    }
    else
    {
        el->next=lis;
        lis=el;
        return lis;
    }
}

Это функция освобождения:

void distruggi_lista_coppie(coppia *lis)
{
    while(lis!=NULL)
    {
        coppia *prossimo=lis->next;
        jr_free(lis);
        lis=prossimo;
    }
}

Не важно, я нашел решение, была функция, в которой мне нужно было найтиМаксимум пара из всего списка, и мне пришлось распечатать это в одиночку.Поэтому я устанавливал в NULL указатель следующего элемента, этот максимальный элемент был вторым последним, поэтому последний элемент был потерян.

Ответы [ 2 ]

1 голос
/ 08 июля 2019

Определенно потерянная память - это память, которая не была освобождена и которая не может быть освобождена, потому что у программы больше нет указателя на память. (См. FAQ Valgrind для более полного списка возможных типов утечек памяти.)

Если это неясно, вот простой пример:

char* buffer;
while (1) {
  buffer = malloc(BUF_LEN);
  if (fgets(buffer, BUF_LEN, stdin) == NULL) break;
  fprintf(stderr, "Read: %s", buffer);
  // process(buffer);
}

Во второй раз в цикле единственный указатель на выделенную память теряется, поскольку он не был освобожден, а единственный указатель на него был перезаписан. Поскольку у программы больше нет указателя на первый выделенный buffer, она не может free() это позже.

В реальной реализации process может делать что-то, что сохраняет указатель (например, вставить его в связанный список), или может даже free() буфер, хотя некоторые сочтут этот плохой дизайн. Если он сохраняет указатель, то память еще не потеряна окончательно, но в какой-то момент программа должна пройти через хранилище сохраненных указателей и освободить каждый из них.

0 голосов
/ 08 июля 2019

Я бы добавил свои собственные jr_malloc и jr_free и просто посмотрел бы, как это называется.Эти функции, в свою очередь, будут вызывать malloc и free.

void *jr_malloc(size_t size)
{
    void *p = malloc(size);
    fprintf(stderr, "malloc: %d %p\n", size, p);
    return p;
}

void jr_free(void *p)
{
    fprintf(stderr, "free: %p\n", p);
    free(p);
}

Возможно, вы сможете сравнить и увидеть, какой p не освобождается.

...