malloc в цикле с использованием valgrind - PullRequest
1 голос
/ 09 марта 2019

У меня проблемы с утечками памяти (ошибка, обнаруженная valgrind).

Итак, моя первая функция:

message *creationCellule() {
    message *cellule;
    cellule = (message *)malloc(sizeof(message));

    if (cellule != NULL) {
        cellule->dateDeb = 0;
        cellule->dateFin = 0;
        cellule->suivant = NULL;
        memset(cellule->text, '\0', TAILLE_MAX);
    }
    return cellule;
}

Возвращает целлюлозу, которая выделена malloc.

Теперь у меня есть это:

void lectureFichier(const char *nomFichier, message **tete) {
    FILE *fp = fopen(nomFichier, "r");
    message *test;
    test = creationCellule();
    int k = 0;

    if (fp != NULL) {
        k = fscanf(fp, "%d %d ", &(test->dateDeb), &(test->dateFin));

        while (k != EOF) {
            fgets(test->text, 100, fp);

            insertion(tete, test);
            test = creationCellule();

            k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
        }
    }
}

В котором я называю creationCellule() в цикле.

Моя проблема в том, что если я помещу free(test) внутрицикл Я теряю весь контекст моего кода и valgrind показывает мне ERROR SUMMARY:213 errors from 19 contexts.

Что мне делать?

Это полный код и вывод valgrind:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tp1.h"

message *creationCellule() {
    message *cellule;
    cellule = (message *)malloc(sizeof(message));

    if (cellule != NULL) {
        cellule->dateDeb = 0;
        cellule->dateFin = 0;
        cellule->suivant = NULL;
        memset(cellule->text, '\0', TAILLE_MAX);
    }

    return cellule;
}

message **recherche(message *tete, int date) {
    message **prec = tete;
    message *cour = *tete;

    while (cour != NULL && cour->dateDeb < date) {
        prec = &(cour->suivant);
        cour = cour->suivant;
    }
    return prec;
}

void insertion(message **tete, message *cellule) {
    message **prec;

    if (cellule != NULL) {
        prec = recherche(tete, cellule->dateDeb);
        cellule->suivant = *prec;
        *prec = cellule;
    }
}

void lectureFichier(const char *nomFichier, message **tete) {
    FILE *fp = fopen(nomFichier, "r");
    message *test;
    test = creationCellule();
    int k = 0;

    if (fp != NULL) {
        k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));

        while (k != EOF) {
            fgets(test->text, 100, fp);

            insertion(tete, test);
            test = creationCellule();

            k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
        }
    }
}

void affichageListe(message **tete) {
    if (tete != NULL) {
        message *tmp = *tete;
        while (tmp != NULL) {
            //printf("jam ktu\n");
            printf("DateDeb = %d \n", tmp->dateDeb);
            printf("DateFin = %d \n", tmp->dateFin);
            printf("Text = %s \n", tmp->text);
            tmp = tmp->suivant;
        }
    }
}

void suppression(message **tete, int valeur, int dateDeb) {
    message **prec;

    prec = recherche(tete, dateDeb);

    //printf("Prec text: %s , prec dateFin: %d\n", (*prec)->text, (*prec)->dateFin);

    if ((*prec) != NULL && (*prec)->dateFin == valeur) {
        (*prec) = (*prec)->suivant;
    }
}

void supprimeObsoletes(message **tete) {
    message *pt = *tete;
    time_t temps;
    struct tm *date;
    int intNum;
    temps = time(NULL);
    date = localtime(&temps);

    char buffer[9];
    if ((date->tm_mon) < 10) {
        sprintf(buffer, "%d0%d%d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday);
    } else {
        sprintf(buffer, "%d%d%d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday);
    }

    intNum = atoi(buffer);

    while (pt != NULL) {
        if ((pt->dateFin) < intNum) {
            printf("KTU HYB %s\n", pt->text);
            suppression(tete, pt->dateFin, pt->dateDeb);
        }
        pt = pt->suivant;
    }
}

void changeDate(int dateChange, int dateInit, message **tete) {
    message *point = *tete;
    //printf("Kjo eshte tete %p:\n", (*point));

    while (point != NULL) {
        if ((point->dateDeb) == dateInit) {
            printf("%d\n", point->dateDeb);
            printf("%s\n", point->text);
            point->dateDeb = dateChange;
        }
        point = point->suivant;
    }
}

int main(int argc, char *argv[]) {
    const char *name = argv[1];
    message *pointeur = NULL;
    message **tete = &pointeur;
    int dateInit = 19973012;
    int dateChange = 20003008;

    FILE *fp = fopen(name, "r");
    lectureFichier(name, tete);
    //changeDate(dateChange, dateInit, tete);

    supprimeObsoletes(tete);

    affichageListe(tete);

    return 0;
}

Заголовок: tp1.h

#ifndef TP1_TEST_H
#define TP1_TEST_H

#define TAILLE_MAX 100

typedef struct cell {
    int dateDeb;
    int dateFin;
    char text[TAILLE_MAX];
    struct cell *suivant;
} message;

message *creationCellule();
message **recherche(message **tete, int date);
void affichageListe(message **tete);
void insertion(message **tete, message *cellule);
void lectureFichier(const char * nomFichier, message **tete);

Файл .txt (добавлен в исполнение)

19973012 20220512 TEXT 1
19980511 19001203 THIS
20011102 20301123 HOUSE
20020809 20301025 HELP

Вывод Valgrind:

Valgrind output

Ответы [ 2 ]

1 голос
/ 09 марта 2019

Функция lectureFichier не освобождает неиспользуемые узлы должным образом.

Вот исправленная версия:

void lectureFichier(const char *nomFichier, message **tete) {
    FILE *fp = fopen(nomFichier, "r");

    if (fp != NULL) {
        for (;;) {
            message *node = creationCellule();
            if (fscanf(fp, "%d%d %99s", &node->dateDeb, &node->dateFin, node->text) == 3) {
                insertion(tete, node);
            } else {
                free(node);
                break;
            }
        }
    }
}
0 голосов
/ 09 марта 2019

следующий предложенный код:

  1. корректно компилирует
  2. правильно обрабатывает ошибки
  3. удален неиспользуемый код
  4. НЕ очищает связанный список, когдавозникает ошибка - вам нужно будет добавить это

и теперь предложенный код:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>



#ifndef TP1_TEST_H
#define TP1_TEST_H

#define TAILLE_MAX 100

struct cell
{
    int dateDeb;
    int dateFin;
    char text[TAILLE_MAX];
    struct cell * suivant;
};
typedef struct cell message;


message * creationCellule( void );
message ** recherche(      message ** tete, int date );
void      affichageListe(  message ** tete );
FILE *    ecrireFichier(   message ** tete );
void      dateNonExpires(  message ** tete );
#endif // TPI_TEST_H




message * creationCellule()
{
    message * cellule = malloc(sizeof(message));
    if( !cellule )
    {
        perror( "malloc failed" );
        exit( EXIT_FAILURE );
    }

    cellule->dateDeb = 0;
    cellule->dateFin = 0;
    cellule->suivant = NULL;
    return cellule;
}


message ** recherche( message ** tete, int date )
{
    message ** prec = tete;
    message * cour = *tete;

    while( cour != NULL && cour->dateDeb < date )
    {
        prec = &(cour->suivant);
        cour = cour->suivant;
    }

    return prec;
}


void insertion(message ** tete, message * cellule)
{
    (void)tete;
    (void)cellule;
    // insert code that does something reasonable
} 


void lectureFichier(const char * nomFichier, message ** tete)
{   
    FILE * fp = fopen(nomFichier, "r");
    if( !fp )
    {
        perror( "fopen failed" );
        exit( EXIT_FAILURE );   
    }

    test = creationCellule();

    while( fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin)) == 2 )
    { 
        fgets(test->text, 100, fp);

        insertion(tete, test);
        test = creationCellule();
    }
}


void affichageListe( message ** tete )
{
    if( tete )
    {
        message * tmp = *tete;
        while( tmp  )
        {
            //printf("jam ktu\n");
            printf( "DateDeb = %d \n", tmp->dateDeb );
            printf( "DateFin = %d \n", tmp->dateFin );
            printf( "Text = %s \n",    tmp->text );
            tmp = tmp->suivant;
        }
    }
}


void suppression( message**tete, int valeur, int dateDeb )
{
    message **prec;

    prec = recherche( tete, dateDeb );
    //printf("Prec text: %s , prec dateFin: %d\n",(*prec)->text,(*prec)->dateFin);

    if( (*prec) != NULL && (*prec)->dateFin == valeur )
    {
            (*prec)=(*prec)->suivant;
    }
}


void supprimeObsoletes(message **tete)
{
    message *pt = *tete;

    time_t temps;
    struct tm *date;

    temps=time(NULL);
    date=localtime(&temps);

    char buffer[9];

    if((date->tm_mon)<10)
    {
        sprintf(buffer,"%d0%d%d",date->tm_year + 1900,date->tm_mon +1,date->tm_mday);
    }

    else
    {
        sprintf(buffer,"%d%d%d",date->tm_year + 1900,date->tm_mon +1,date->tm_mday);
    }

    int intNum=atoi(buffer);

    while( pt )
    {
        if( (pt->dateFin) < intNum )
        {
            printf( "KTU HYB %s\n", pt->text );
            suppression( tete, pt->dateFin, pt->dateDeb );
        }

        pt=pt->suivant;
    }
}



int main(int argc, char * argv[])
{
    if( argc != 2 )
    {
        fprintf( stderr, "USAGE: %s filename\n", argv[0] );
        exit( EXIT_FAILURE );
    }

    const char * name  = argv[1];
    message * pointeur = NULL;

    lectureFichier( name, &pointeur );
    supprimeObsoletes(    &pointeur );
    affichageListe(       &pointeur );

    while( pointeur )
    {
        message *current = pointeur;
        pointeur = pointeur->suivant;
        free( current );
    }

    return 0;
}
...