【问题标题】:Memory leaks problems using valgrind even after fclose即使在 fclose 之后使用 valgrind 也会出现内存泄漏问题
【发布时间】:2019-03-10 00:18:35
【问题描述】:

我在使用 valgrind 时遇到问题,问题出在这个函数中,我显然有内存泄漏。

void lectureFichier(const char * nomFichier, message ** tete){

      message * test=creationCellule();

        FILE * fp = fopen(nomFichier, "r");

        if(!fp)
        {

                perror("fopen failed\n");
                exit( EXIT_FAILURE );
        }


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


               if(fscanf(fp,"%d %d ",&(test->dateDeb), &(test->dateFin))!=2)
               {
                        fprintf(stderr,"fscanf of first two\n");
                        free(test);

                        exit(EXIT_FAILURE);

               }

                fgets(test->text,100,fp);
                insertion(tete,test);
                test=creationCellule();

        }
        fclose(fp);
     }

看看valgrind的结果:

我找不到问题。你有什么建议吗?

这是包含上述函数的完整代码,当我将此代码与 VALGRIND 一起使用时,它给出的结果如上图所示:

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

message * creationCellule(){

    message * cellule=NULL;
    free(cellule);
    cellule=malloc(sizeof(message));
    if(!cellule)
    {
            perror("malloc failes\n");
            exit(EXIT_FAILURE);
    }


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




    return cellule;
}

/*bejme recherche per date de deb se eshte trie nga date deb*/
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;

}

/*la prochaine fois il faut venir avec un makefile*/
void insertion(message ** tete, message * cellule){

    (void)tete;
    (void)cellule;

    message ** prec;


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


} 


/*duhet te lexojme fichier ne fillim dhe kete fichier do e krijojme ne vete*/
void lectureFichier(const char * nomFichier, message ** tete){



    message * test=creationCellule();

        FILE * fp = fopen(nomFichier, "r");



        if(!fp)
        {

                perror("fopen failed\n");
                exit( EXIT_FAILURE );
        }


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


               if(fscanf(fp,"%d %d ",&(test->dateDeb), &(test->dateFin))!=2)
               {
                        fprintf(stderr,"fscanf of first two\n");
                        free(test);

                        exit(EXIT_FAILURE);

               }

                fgets(test->text,100,fp);
                insertion(tete,test);
                test=creationCellule();

        }

                fclose(fp);


     }  




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

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

                (*prec)=(*prec)->suivant;
        }

}

//EXERCICE 3

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;
        lectureFichier(name, &pointeur);
        supprimeObsoletes(&pointeur);
        affichageListe(&pointeur);

        while(pointeur)
        {


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


        }
    return 0;

}

【问题讨论】:

  • 你忘记fclose文件了吗?
  • @Serge 不,我已经添加了它,它仍然显示同样的问题
  • 然后忽略它。存在不应释放的内部 libc 缓冲区。
  • @Serge 请看一下整个代码
  • 您的 valgrind 报告指向内部 fopen 缓冲区。没有别的了。所以,看起来程序本身没有泄漏。

标签: c memory-leaks valgrind


【解决方案1】:

您的 valgrind 日志显示“前两个的 fscanf”作为程序输出的一部分。这部分发生在 fscanf 调用在循环内失败时。你打电话给exit,但不要关闭文件。您需要先关闭文件:

           if(fscanf(fp,"%d %d ",&(test->dateDeb), &(test->dateFin))!=2)
           {
                    fprintf(stderr,"fscanf of first two\n");
                    fclose(fp);
                    free(test);

                    exit(EXIT_FAILURE);

           }

【讨论】:

  • exit() 关闭打开的 stdio 文件流。
  • @Shawn 我还可以在 exit() 中使用什么,因为我不允许使用它,但如果我删除它,我会从 valgrind 得到错误?
  • @dbush 非常感谢你!!我有一个问题,为什么 fscanf 失败了,我进入了 if?
  • @MimozaQati 这取决于您的数据是什么样的。您连续调用它两次,一次在循环顶部,一次在 if 中,前者被丢弃。您可能不希望在 fscanf 中使用它,所以如果是这种情况,请使用 Mirko 的答案。
  • @MimozaQati“仍然可以访问”内存不是错误。
【解决方案2】:
void lectureFichier(const char * nomFichier, message ** tete)
{
    message * test=creationCellule();

    FILE * fp = fopen(nomFichier, "r");
    if(!fp)
    {
        perror("fopen failed\n");
        exit( EXIT_FAILURE );
    }

    while(fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin))==2)
    {
//        Here you are reading again. That's not what you want.
//        if(fscanf(fp,"%d %d ",&(test->dateDeb), &(test->dateFin))!=2)
//        {
//            fprintf(stderr,"fscanf of first two\n");
//            free(test);
//            exit(EXIT_FAILURE);
//        }
        fgets(test->text,100,fp);
        insertion(tete,test);
        test=creationCellule();
    }
    // Here you can free the last test, because it is not used
    free(test);
    fclose(fp);
}

【讨论】:

    【解决方案3】:

    如果您的问题是内存泄漏,那么您应该将 free(fp) 用于动态分配的指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-23
      • 1970-01-01
      • 1970-01-01
      • 2016-06-29
      • 2021-11-19
      • 2015-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多