c valgrind的快速内存泄漏

时间:2018-01-28 21:48:37

标签: c list memory-leaks quicksort heap-memory

我在为这个c快速排序代码初始化内存时遇到了问题。 排序算法运行完美。 我唯一的问题是释放内存。

这是我的代码:

#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "quicksort.h"

/*****************************************************
 * Die benoetigten structs findet Ihr in quicksort.h *
 *****************************************************/

void init_list(list* mylist)
{
// HIER Liste initialisieren
    mylist->first=NULL;
    mylist->last=NULL;
}


// Diese Funktion fügt Listenelemente an die Liste an
void insert_list(list_element* le, list* mylist)
{
    // HIER Code einfügen
    if (mylist->first == NULL) {
        le->next = NULL;
        mylist->first = le;
        mylist->last = le;
    }
    else {
        le->next = mylist->first;
        mylist->first = le;
    }
}
// Speicher für Listenelemente wieder freigeben
void free_list(list* mylist)
{
    // HIER Code einfügen
    list_element *current = mylist->first;
    list_element *alt;
    while (current != NULL) {
        alt = current;
        current = current->next;
    free (alt);
    }
    free (current);
}


// Namen, Zahlen Paare in Liste einlesen
void read_data(char* filename, list* mylist)
{
        // HIER Code einfügen:
        // * Speicher allozieren
        // * Daten in list_element einlesen
        // * insert_front benutzen um list_element in Liste einzufügen
    FILE *fprint = fopen(filename, "r");
    if (fprint == NULL){
        perror("input file könnte nicht geöffnet werden!");
    }
    while (1){
        char buffer[100];
        int counter ;
        int return_fscanf = fscanf (fprint ,"%s %d",buffer,&counter);
        if (return_fscanf == EOF){
            break;
        }
        if (return_fscanf != 2){
            printf ("Datei hat ungültiges Format.\n");
            break;
        }
        list_element *new_elem = malloc (sizeof (list_element));
        new_elem->password = malloc (sizeof (char)*strlen(buffer)+1);
        new_elem->count= counter;
        strncpy(new_elem->password, buffer,strlen(buffer));
        new_elem->next = NULL;
        insert_list (new_elem , mylist );
    }
}

// Liste teilen. Teillisten werden in left und right zurück gegeben
list_element* partition( list* input, list* left, list* right )
{
    // HIER Code einfügen:
    // parition() Funktion implementieren
    list_element* pivot=input->first;
    init_list(left);
    init_list(right);
    list_element* t=input->first->next;
    while(t!=NULL)
    {
        list_element* tnext=t->next;
        if((t->count) < (pivot->count))
        {
            insert_list(t,left);
        }
        else 
        {
            insert_list(t,right);
        }
        t=tnext;
    }
    return pivot;   
}

// Hauptfunktion des quicksort Algorithmus
void qsort_list(list* mylist)
{
    // HIER Code einfügen
    if(mylist->first == mylist->last) {
    }else{
        list LFT;
        list RGT;
        list* left=&LFT;
        list* right=&RGT;
        list_element* pivot = partition(mylist, left, right);
       qsort_list(left);
       qsort_list(right);

      if(left->first == NULL){
         mylist->first = pivot;
        }else{
            mylist->first = left->first;
            left->last->next = pivot;
        }
      if(right->first == NULL){
         pivot->next = 0;
         mylist->last = pivot;
        }else{
            pivot->next = right->first;
            mylist->last = right->last;
        }
    }
}

// Liste ausgeben
void print_list(list* mylist)
{
    // HIER Code einfügen:
    // * Laufe über die list_element in mylist und gebe sie aus.
    list_element *elem = mylist->first;
    while (elem != NULL) {
        printf("Passwort : %-15s Haeufigkeit : %-15d\n", elem->password ,             
elem->count);
    elem = elem->next;
    }
    printf("\n");
}

quicksort.h,其中包含struct,如下所示:

`typedef struct list_element list_element;

struct list_element {
    char *password;
    int count;
    list_element* next;
};

typedef struct list list;

struct list {
list_element* first;
list_element* last;
};
void init_list( list* mylist );
void insert_list( list_element* le, list* mylist );
void free_list( list* mylist );
void read_data( char* filename, list* mylist );
list_element* partition( list* input, list* left, list* right );
void qsort_list( list* mylist );
void print_list( list* mylist );`

这里是带有leak-check = full的valgrind报告:

==244== HEAP SUMMARY:
==244==     in use at exit: 1,343 bytes in 101 blocks
==244==   total heap usage: 203 allocs, 102 frees, 4,767 bytes allocated
==244==
==244== 791 bytes in 100 blocks are definitely lost in loss record 2 of 2
==244==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==244==    by 0x4009D3: read_data (in /mnt/c/Users/YOGA/Desktop/introprog-wise1718/Aufgaben/Blatt10/Vorgaben/quicksort)
==244==    by 0x400CBD: main (in /mnt/c/Users/YOGA/Desktop/introprog-wise1718/Aufgaben/Blatt10/Vorgaben/quicksort)
==244==
==244== LEAK SUMMARY:
==244==    definitely lost: 791 bytes in 100 blocks
==244==    indirectly lost: 0 bytes in 0 blocks
==244==      possibly lost: 0 bytes in 0 blocks
==244==    still reachable: 552 bytes in 1 blocks
==244==         suppressed: 0 bytes in 0 blocks
==244== Reachable blocks (those to which a pointer was found) are not shown.
==244== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==244==
==244== For counts of detected and suppressed errors, rerun with: -v
==244== Use --track-origins=yes to see where uninitialised values come from
==244== ERROR SUMMARY: 101 errors from 2 contexts (suppressed: 0 from 0)

编辑:我修复了漏洞。我将原始代码保留未经编辑,以便读者可以看到更改。

我编辑了void free_list,但是我仍然有一个由fopen命令引起的泄漏,它在void read_data的末尾需要一个fclose命令。

void free_list(list* mylist)
{
    // HIER Code einfügen
    list_element *current = mylist->first;
    list_element *alt=NULL;
    while (current) {
        alt = current;
        current = current->next;
        free(alt->password);
        free (alt);
    }
}

2 个答案:

答案 0 :(得分:1)

问题是你要分两行(通过malloc)分配内存,但是你以后不会释放所有的内存。

从我可以看到你错过了相应的malloc using的免费...但我的c ++生锈了,所以我可能错过了一个。

答案 1 :(得分:0)

我看到 fopen 的电话,但没有打电话给 fclose ?也许那是你的泄密?