IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème fopen et malloc pour des milliers de fichiers


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 79
    Points : 21
    Points
    21
    Par défaut Problème fopen et malloc pour des milliers de fichiers
    Bonjour à tous,

    Afin de compléter une fonctionnalité de mon application et de pouvoir mettre en place un apprentissage je dois pouvoir établir des statistiques sur la fréquence des mots (mots appartenant à un lexique que j'ai mis en place dans un fichier texte: un mot par ligne ordonné alphabétiquement)sur de nombreux fichiers(corpus établi contenant 5000 fichiers html parsés en texte brut) situés dans des répertoires différents.

    Malheureusement je constate que lorsque les fichiers sont en très grand nombres les derniers fichiers (>2000) ne peuvent pas être analysés correctement (voir pas du tout) du fait que l'ouverture du fichier me renvoi parfois la valeur NULL ou/et l'allocation du buffer devant recevoir ce fichier ne fonctionne pas correctement.
    Ce qui est étrange c'est que ces fichiers (indiquant des erreurs pour le traitement statistiques) existent, ne sont pas vides, et leurs tailles est bien > 0 (allocation du buffer pourtant NULL) mais l'analyse ne fonctionne pas.
    En revanche, le traitement de ces fichiers avec là même fonction mais de manière indépendante fonctionne correctement.

    J'ai donc lû de nombreux posts depuis 2 jours abordant les problèmes liée à une utilisation simultanée de fopen (pourtant bien fermé), ou à l'allocation du buffer mais cela n'a pas résolu mon problème.

    Merci d'avance pour vos conseils, et pour y voir un peu plus clair ci dessous la fonction non optimisée et un peu fouillie me permettant d'établir les statistiques (au préalable j'ai une fonction qui me liste tous les répertoires de mon corpus et pour chaque répertoire j'appelle donc la fonction compter_mots_fichiers() )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    int compter_mots_fichiers(char * rep_convert, char * fichier_mots, char * nom_fichier_2,  char * nom_fichier_3)
    {
         char  * buffer,* recherche, * str_sans_espace,ligne [1024];
         int nbr_conv=0, nombre_fichier=0, compt = 0, nbr_total_mot = 0, nombre_rep=0, nb_total,nb_fichier ;
         struct dirent *lecture;
         DIR  *rep2;     
         FILE  *fichier_2, *fichier_3, *fichier_mot;
     
         rep2 = opendir(rep_convert);    
     
         while ((lecture = readdir(rep2)))   //parcours des fichiers dans le répertoire
              nombre_rep++;
     
         fichier_2 = fopen(nom_fichier_2, "wb");            // fichier final contenant uniquement les liens 
         fichier_3 = fopen(nom_fichier_3, "wb");            // fichier final contenant uniquement les liens 
         fprintf(fichier_2, "STATISTIQUES DES DOCUMENTS DE %s \n\n", rep_convert);
         fprintf(fichier_3,"STATISTIQUES DES DOCUMENTS DE %s \n\n", rep_convert );
     
         fichier_mot = fopen ( fichier_mots, "rb" ); 
     
         if ( fichier_mot != NULL )
         {
            while ( fgets ( ligne, sizeof ligne, fichier_mot ) != NULL ) 
            {
                  str_sans_espace=trim(ligne);  //efface les espaces inutiles 
                  recherche=str_sans_espace;
                  nb_total=0;
                  nb_fichier=0;
                  DIR *rep;
                  rep = opendir(rep_convert);   
     
                while ((lecture = readdir(rep)))   //parcours des fichiers dans le répertoire
                {
                    nombre_fichier++;
                    int continuer=1;          
     
                    if(nombre_fichier>2 && nombre_fichier!=nombre_rep)//&& nombre_fichier<5)          //on ignore . et ..
                    {      
                            nbr_conv++;                                   
                            char lien_ini[255]={0};
                            char *nom_fichier_seul;                       
     
                            sprintf(lien_ini,"%s%s",rep_convert, lecture->d_name );
                            nom_fichier_seul = strchr(lecture->d_name, '.');         //suppression de l'extension  
     
                            if(nom_fichier_seul!=NULL)
                              *nom_fichier_seul = '\0';
     
                            FILE *fichier;
                            int taille_fichier;                    
                            char *balise_debut, *debut;              
     
                            fichier = fopen (lien_ini, "rb");
     
                            if (fichier == NULL)
                            {
                              printf("\n fichier ini vide %s, %d \n", lien_ini, nombre_fichier);
                             // return 1;
                            } 
                            else
                            {                                                                                
                                fseek (fichier, 0 , SEEK_END);                    // determine la taille du fichier
                                taille_fichier = ftell (fichier);
                                rewind (fichier);                  
                                buffer = malloc (taille_fichier);         //allocation mémoire pour le buffer d                         
     
                                if (buffer ==  NULL)                              //si buffer vide, erreur
                                {
                                       printf("\n buffer vide erreur %s => %d \n",lien_ini, taille_fichier);
                                  //     return 2;        
                                }
                                else
                                {              
                                    fread (buffer, 1, taille_fichier, fichier);       // copie du fichier dans le buffer/tampon                                    
                                    fclose(fichier);
                                     balise_debut = recherche;                          
     
                                     while (continuer == 1)
                                     {
                                         debut = strstr(buffer, balise_debut);             //recherche dans le buffer   
     
                                         if (debut != NULL) 
                                         {   
                                             nbr_total_mot++;
                                             nb_total++;                     
                                             int fin_balise=strlen(buffer)-strlen(debut)+strlen(balise_debut) ;       
                                             buffer=buffer+fin_balise; 
                                             debut=strstr(buffer,balise_debut);         //indication du nouveau début                                          
                                         }
                                         else 
                                         {
                                                continuer = 0;                                   
                                         }                                                 
                                     }                                                       
     
                                     nb_fichier = nb_total-nb_fichier;
     
                                     if(nb_fichier>0 && nb_total>0 )
                                     {
                                         printf("Recherche du mot '%s' dans %s : %d \n", balise_debut, lien_ini, nb_fichier);
                                          fprintf(fichier_2,"Recherche du mot '%s' dans %s : %d \n", balise_debut, lien_ini, nb_fichier);
                                     }
                                     nb_fichier= nb_total; 
                                 }                              
                            }                                                                     
                    }                      
                 } 
     
                 printf("\n\n TOTAL mot %s dans '%s' : %d \n\n", recherche, rep_convert,nb_total);   
                 fprintf(fichier_2,"\n TOTAL mot '%s' dans %s : %d \n\n", recherche, rep_convert,nb_total );
                 fprintf(fichier_3,"%s : %d \n", recherche,nb_total );
                 nb_total=0;
                 nombre_fichier=0;            
           }               
     
          fclose(fichier_mot); 
         }
         else
           printf("\nprobleme fichier mot\n");     
     
     
         fprintf(fichier_2,"\n NOMBRE TOTAL MOTS : %d\n\n", nbr_total_mot);
         fprintf(fichier_2,"\0");
         fclose(fichier_2); 
         fclose(fichier_3);  
         free(buffer);  
     
       return 3;      
    }

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    Tu fais un malloc() dans une boucle et le free correspondant hors de la boucle -> ça sent la fuite de mémoire.

  3. #3
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Bonjour,

    Médinoc pointe un gros problème de fuite mémoire, surtout si les fichiers sont gros car tu alloues un buffer de la taille du fichier et tu ne les libères pas au bon moment.
    Je suppose que tu travailles dans un environnement windows.
    Tu dis que tu n'as pas optimisé (normal on ne peut pas optimiser avant que ce soit fonctionnel), mais je voudrais pointer peut-être un problème de choix de structure et d'algorithme. Pour chaque mot dont tu veux obtenir les fréquences tu parcours 5000 fichiers ... ça fait beaucoup de perte de temps en ouverture/accès/fermeture de fichiers.
    Il serait peut-être plus intéressant de ne parcourir les 5000 fichiers une fois pour te constituer une base de donnée que tu n'aurais plus qu'à (toujours se méfier des pluka) interroger pour avoir rapidement tes réponses. Cette base de donnée n'est pas obligatoire une «vraie base de donnée» (ne pense pas obligatoirement mysql ou pire), mais peut simplement être une table de hashage ou un trie (une sdd adaptée dans ton cas à mon avis) en mémoire, ou éventuellement déporté sur le hd avec sqlite (ce qui peut-être bien pratique).
    Enfin cela dépend aussi du nombre de mots dont tu cherches les fréquences, combien de fois tu seras amenée à lancer cette requête, comment évoluera ton corpus, etc ...

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Pour rajouter mon grain de sel (ou de sable).

    Ta fonction fait beaucoup de choses, peut être qu'un découpage plus fin permettrait de mieux découper le code et ainsi mieux voir les problèmes.

    Autre chose, au tout début :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int nombre_rep=0;
         DIR  *rep2;   
    struct dirent *lecture;
         rep2 = opendir(rep_convert);    
     
         while ((lecture = readdir(rep2)))   //parcours des fichiers dans le répertoire
              nombre_rep++;
    il manque un closedir() (et un file descripteur ouvert et pas fermé ).
    De plus, tu comptes des entrées de répertoire (donc des fichiers, des répertoires, des liens, des ...) et ta variable s'appelle nombre_rep. Pas facile à comprendre pour les autres

    Comme en plus, tu n'utilises pas le résultats de readdir(), tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
         while (readdir(rep2))   //parcours des fichiers dans le répertoire
    et puis j'aime bien les tests explicites :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
         while (readdir(rep2) != NULL)   //parcours des fichiers dans le répertoire
    C'est plus facile à lire et puis on voit directement ta condition de sortie.

    Donc au final :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
         DIR  *rep2;   
         int nombre_entry = 0;
         rep2 = opendir(rep_convert);    
         while(readdir(rep2))   //parcours des fichiers dans le répertoire
              nombre_entry++;
         closedir(rep2);
    Et même, cela peut devenir une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    int count_entries(const char * repertoire)
    {
       // test la valeur de repertoire
       if( (repertoire == NULL) || (*repertoire == 0) )
       {
          // repertoire est invalide
          assert(0);   // juste pour avoir une trace lors du debug, je ne sais pas si cela existe dans ton environnement
          return 0;
       }
     
       // ouverture du repertoire
       DIR *rep = opendir(repertoire);    
       if(rep == NULL)
       {
          // impossible d'ouvrir repertoire (inexistant, droit, ???
          assert(0);   // juste pour avoir une trace lors du debug, je ne sais pas si cela existe dans ton environnement
          return 0;
       }
     
       int nb_entry = 0;
       // parcours des entrees dans le répertoire
       // toujours des accolades, même pour une seul ligne de code. Tu seras bien content d'avoir déjà les accolades si tu dois ajouter une autre instruction et puis c'est plus facile à suivre lorsque l'on est dans le debugger que "while(readdir(rep)) nb_entry++;" sur une seule ligne
       while(readdir(rep))   
       {
          nb_entry++;
       }
     
       // fermeture du repertoire
       closedir(rep);
     
       // fin
       return nb_entries;
    }
    Voilà, c'est l'idée et pareil pour le reste, des fonctions simples de quelques lignes et cela sera plus facile pour tout le monde.

    Au fait, je n'ai pas testé le code que je te propose , les éventuels bugs qui restent dedans sont 100% copyright ram-0000, interdit de les réutiliser

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 79
    Points : 21
    Points
    21
    Par défaut
    Veuillez m'excuser de ma réponse tardive, et avant tout merci pour ces conseils. J'ai donc ajouté la fonction pour compter les répertoires, les closedir() nécessaires puis corrigé le mauvais emplacement de la libération du buffer dans la boucle mais l'analyse statistiques plante toujours de la même manière.

    Pour la question du choix, je parcours en fait pour chaque mot du lexique chacun des fichiers (entre 5 et 70 ko) du fait que mon lexique soit de petite taille (seulement 90 mots) mais surtout du fait que j'ai souhaité implémenter la fonction la plus simple (qui au final me complique la vie) possible pour ne pas perdre de temps sur cette partie (qui me sert juste de test) développée effectivement sous windows pour le moment.

    Je tente encore de trouver solution(s) à mon problème et si aucune améliorations d'ici demain je reprendrai alors la fonction en modifiant la structure.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 79
    Points : 21
    Points
    21
    Par défaut
    Après suppression de lignes inutiles et principalement de l'ouverture de certains fichiers mon bug survient toujours au même endroit donc j'en arrive à me dire que le problème ne viendrai pas d'une limitation par processus pour l'ouverture.
    Mon buffer étant remis à NULL pour chaque nouveau fichier, je pense que le problème ne viendrait pas non plus du malloc.

    Serait t-il possible que cela vienne de mon environnement ? (Dev C++ sous windows)

    PS: voici mon code un peu plus simplifié

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    int compter_mots_fichiers(char * rep_convert, char * fichier_mots, char * nom_fichier_2,  char * nom_fichier_3)
    {
         int nbr_conv=0, nombre_fichier=0, compt = 0, nbr_total_mot = 0, nombre_rep=0, nb_total,nb_fichier ;
         struct dirent *lecture;
         DIR  *rep2;
         char  * recherche,ligne [1024];
         FILE  *fichier_2, *fichier_3, *fichier_mot;     
     
         nombre_rep=count_entries(rep_convert);
         fichier_mot = fopen ( fichier_mots, "rb" );
     
         if ( fichier_mot != NULL )
         {
            while ( fgets ( ligne, sizeof ligne, fichier_mot ) != NULL ) 
            {
                  recherche=trim(ligne);
                  nb_total=0;
                  nb_fichier=0;
                  DIR *rep;
                  rep = opendir(rep_convert);   
     
                while ((lecture = readdir(rep)))   //parcours des fichiers dans le répertoire
                {
                    nombre_fichier++;
                    int continuer=1;          
     
                    if(nombre_fichier>2 && nombre_fichier!=nombre_rep)//&& nombre_fichier<5)          //on ignore . et ..
                    {      
                            nbr_conv++;                                   
                            char lien_ini[255]={0};
                            char *nom_fichier_seul;                       
                            char * buffer=NULL;
                            FILE *fichier;
                            int taille_fichier;                    
                            char *balise_debut, *debut; 
     
                            sprintf(lien_ini,"%s%s",rep_convert, lecture->d_name );
                            nom_fichier_seul = strchr(lecture->d_name, '.');         //suppression de l'extension                                                  
                            if(nom_fichier_seul!=NULL)
                               *nom_fichier_seul = '\0';            
     
                            fichier = fopen (lien_ini, "rb");
     
                            if (fichier == NULL)
                            {
                                printf("\n fichier ini vide %s, %d \n", lien_ini, nombre_fichier);
                            } 
                            else
                            {                                                                                
                                fseek (fichier, 0 , SEEK_END);                    // determine la taille du fichier
                                taille_fichier = ftell (fichier);
                                rewind (fichier);                  
                                buffer = malloc (taille_fichier);         //allocation mémoire pour le buffer d                         
     
                                if (buffer ==  NULL)                              //si buffer vide, erreur
                                {
                                       printf("\n buffer vide erreur %s => %d \n",lien_ini, taille_fichier);       
                                }
                                else
                                {              
                                    fread (buffer, 1, taille_fichier, fichier);       // copie du fichier dans le buffer/tampon                                    
                                    fclose(fichier);
                                     balise_debut = recherche;                          //meilleur recherche mais retirer 1000
     
                                     while (continuer == 1)
                                     {
                                         debut = strstr(buffer, balise_debut);             //recherche dans le buffer de la balise <cite> contenant les liens   
     
                                         if (debut != NULL) 
                                         {   
                                             nbr_total_mot++;
                                             nb_total++;                     
                                             int fin_balise=strlen(buffer)-strlen(debut)+strlen(balise_debut) ;       
                                             buffer=buffer+fin_balise; 
                                             debut=strstr(buffer,balise_debut);         //indication du nouveau début                                          
                                         }
                                         else 
                                         {
                                                continuer = 0;                                   
                                         }                                                 
                                     }                                                       
     
                                     nb_fichier = nb_total-nb_fichier;
                                     //  if(nb_fichier>0 && nb_total>0 )
                                     {
                                            printf("Recherche du mot '%s' dans %s : %d \n", balise_debut, lien_ini, nb_fichier);
                                    //      fprintf(fichier_2,"Recherche du mot '%s' dans %s : %d \n", balise_debut, lien_ini, nb_fichier);
                                     }
                                     nb_fichier= nb_total; 
                                 }                              
                            }  
     
                    }                      
                 } 
                closedir(rep);
                printf("\n\n TOTAL mot %s dans '%s' : %d \n\n", recherche, rep_convert,nb_total);   
                nb_total=0;
                nombre_fichier=0;            
           }               
       //   free(buffer);        
          fclose(fichier_mot); 
         }
         else
           printf("\nprobleme fichier mot\n");     
     
       return 1;      
    }
    Et le code de la fonction appelante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    int compter_mots_corpus(char * rep_convert, char * fichier_mots, char * nom_fichier_2,  char * nom_fichier_3)
    {
          DIR *rep;
          struct dirent *lecture_doss;
          int nombre_fichier=0;
     
          rep = opendir(rep_convert);   
     
            while ((lecture_doss = readdir(rep)))   //parcours des fichiers dans le répertoire
            {
                char lien_ini[150]={0}, lien_fin_test[150]={0};
                char *lien_fin, *lien_fin_simple;
                nombre_fichier++;
     
     
                if(nombre_fichier>2)//&& nombre_fichier<5)          //on ignore . et ..
                {
                    lien_fin = concatene(nom_fichier_2, lecture_doss->d_name);
                    mkdir(lien_fin);
                    sprintf(lien_fin_test,"%s%s",lien_fin, "/simple_stat_all_fichier_corpus.txt" );
                    lien_fin = concatene(lien_fin,"/stat_all_fichier_corpus.txt");                
                    sprintf(lien_ini,"%s%s/",rep_convert, lecture_doss->d_name );             
                    compter_mots_fichiers(lien_ini, fichier_mots, lien_fin, lien_fin_test);
                 // wait(1);
                }
            }     
            closedir(rep);      
       return 3;      
    }
    Merci d'avance

  7. #7
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par Jérém08 Voir le message
    Après suppression de lignes inutiles et principalement de l'ouverture de certains fichiers mon bug survient toujours au même endroit donc j'en arrive à me dire que le problème ne viendrai pas d'une limitation par processus pour l'ouverture.
    Mon buffer étant remis à NULL pour chaque nouveau fichier, je pense que le problème ne viendrait pas non plus du malloc.

    Serait t-il possible que cela vienne de mon environnement ? (Dev C++ sous windows)

    [...]
    Bonjour,

    plusieurs malloc, aucun free -> bug
    à chaque malloc son free et tu auras moins de problèmes.
    Attention : mettre buffer à NULL ne libère pas la mémoire, il n'y a pas de GC en C, toute allocation doit être libérée explicitement à la main.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 79
    Points : 21
    Points
    21
    Par défaut
    Le hic c'est qu'un free(buffer) peut importe son emplacement (tout testé pour le cas ou je l'aurai mal placé) me fait carrément stoppé le déroulement du programme après quelques traitements de fichiers.
    Je me suis donc dit que c'était parce que mon buffer était déclaré dans ma boucle, j'ai donc retesté comme dans ma première version posté avec la déclaration du buffer au début de ma fonction mais toujours pareil pour le moment..

  9. #9
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par Jérém08 Voir le message
    Le hic c'est qu'un free(buffer) peut importe son emplacement (tout testé pour le cas ou je l'aurai mal placé) me fait carrément stoppé le déroulement du programme après quelques traitements de fichiers.
    Je me suis donc dit que c'était parce que mon buffer était déclaré dans ma boucle, j'ai donc retesté comme dans ma première version posté avec la déclaration du buffer au début de ma fonction mais toujours pareil pour le moment..
    Tu utilises beaucoup de malloc dans ton programme ?
    sinon l'emplacement est souvent clair et jamais aléatoire ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      buffer = malloc (taille_fichier);         //allocation mémoire pour le buffer d                         
      if (buffer ==  NULL)                              //si buffer vide, erreur
      {
        printf("\n buffer vide erreur %s => %d \n",lien_ini, taille_fichier);       
        ICI ON QUITTE LE PROGRAMME -> DE TOUTE FAÇON IL N'Y A PLUS DE MÉMOIRE
      }
      else
      {
        Ici buffer est valide donc on peut travailler avec
        ...
        on arrive à la fin -> plus besoin du buffer on peut le libérer
        free(buffer);
      }
    Si tu as d'autres erreurs c'est qu'il s'agit d'autres erreurs ...
    Pour info, quel est le format des documents parsés ?
    quelle est la taille maximum des fichiers parsés ?

  10. #10
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut
    ton code sera correct avec la mémoire quand tu pourra dire quand est libéré chaque appel effectif de malloc (donc, chacun des passages dans une boucle…).

    Au passage, essaie de quitter dev-cpp, qui est basé sur un compilateur périmé.
    Le langage a évolué, et il y aurait quelques bugs dedans.
    Tu peux te tourner vers code::blocks ou visual studio (express).

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    Un free() doit être fait sur l'adresse retournée par malloc(): En ligne 74 tu modifies le pointeur buffer, d'où comportement indéfini (erreur, plantage) lors du free().

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 79
    Points : 21
    Points
    21
    Par défaut
    Je vais prochainement changé complétement d'environnement et d'OS (linux) car je vais avoir besoin d’exécuter des scripts Perls et ce sera plus simple à gérer.
    Concernant mes données parsées, elles sont directement extraites à partir du web et stockées dans des fichiers .html (avec libcurl) que je parse ensuite à ma guise dans des fichiers .txt
    Je pense que tu as trouvé l'erreur Médinoc, mais je suis pourtant obligé de modifier le buffer pour permettre de lancer la recherche dans la suite du fichier. Dois-je donc ré-allouer ce même buffer ?

    edit: Modifiant ce buffer j'ai donc tenté de le réallouer avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     buffer = realloc(buffer, (taille_fichier+ fin_balise));
    mais le free(buffer) stop toujours l'execution

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    Il y a une différence entre modifier un buffer et modifier un pointeur vers lui. Les pointeurs peuvent être copiés plus facilement que les buffers.

    Tu peux donc utiliser un second pointeur vers le même buffer:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char * buffer = malloc(taille)
    fread(buffer);
    {
        char const *buffer2 = buffer;
        char const *debut;
        /* Lecture en utilisant buffer2 et debut, qui peuvent être modifiés en toute impunité */
    }
    free(buffer);

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 79
    Points : 21
    Points
    21
    Par défaut
    MErciiiiiiiiiiiiiiiiiiii ça fonctionne parfaitement avec le nouveau pointeur

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. script perl pour charger des milliers de fichiers en une connexion
    Par mariogarcia dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 23/05/2013, 11h59
  2. Réponses: 2
    Dernier message: 27/03/2013, 12h30
  3. [XL-2007] Problème avec la lecture VBA des Propriétés personnalisées / fichiers XLSX
    Par Fambross dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 03/02/2013, 06h53
  4. malloc pour des grandes tailles mémoires
    Par SuperSeb95 dans le forum C
    Réponses: 9
    Dernier message: 21/05/2012, 14h40
  5. Réponses: 3
    Dernier message: 05/12/2009, 12h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo