Segmentation fault aléatoires !!

Segmentation fault aléatoires !! - C - Programmation

Marsh Posté le 23-01-2004 à 02:33:48    

Slt !
 
Je deviens fou !!
Je fais un petit programme qui répertorie la liste des fichiers
et répertoires à partir d'une racine donnée.
Le problème est qu'il fonctionne avec certaines racines,
et me fait une "segmentation fault" avec d'autres !
Je ne sais plus comment faire.
 
Normalement je fais des "free()" lorsque je n'ai plus besoin
de pointeurs, mais je me suis aperçu que si j'en faisais ça merdait dans certains cas contrairement à lorsque je n'en fais pas.. Mais juste dans certains cas !!
 
Pourriez-vous m'éclaircir SVP car je ne vois pas du tout le pb!
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/stat.h>
  4. #include <dirent.h>
  5. #include <string.h>
  6. int filtre (const struct dirent* dir) {
  7.   if ((strcmp(dir->d_name,"." )==0) || (strcmp(dir->d_name,".." )==0)) {
  8.     return 0;
  9.   }
  10.   return 1;
  11. }
  12. int is_directory (char* dir) {
  13.   /* Retourne 1 si 'dir' correspond à un répertoire, sinon retourne 0 */
  14.   struct stat buf;
  15.   if(stat(dir,&buf)) {
  16.     perror("stat" );
  17.     exit(1);
  18.   }
  19.   if(S_ISDIR(buf.st_mode)) { /* Si c'est un répertoire */
  20.     return 1;
  21.   }
  22.   else return 0;
  23. }
  24. void arbo2 (char* racine) {
  25.   struct dirent** namelist = NULL;
  26.   char* chemin = NULL;
  27.   char* tmp = NULL;
  28.   int len, n, i;
  29.   len = strlen(racine);
  30.   chemin = (char*) malloc((len+1)*sizeof(char));
  31.   strcpy(chemin, racine);
  32.   chemin[len] = '\0';
  33.   len = strlen(chemin);
  34.   if((n = scandir(chemin, &namelist, filtre, alphasort)) < 0) {
  35.     fprintf(stderr, "irkm: %s: No such file or directory\n", chemin);
  36.     exit(1);
  37.   }
  38.   /* Nécessité d'avoir un '/' à la fin de 'chemin' */
  39.   if(chemin[len-1]!='/') {
  40.     chemin = (char*) realloc(chemin, (len+1)*sizeof(char));
  41.     strcat(chemin, "/" );
  42.     len = strlen(chemin);
  43.   }
  44.   for (i=0; i<n; i++) {
  45.     tmp = (char*) malloc((len+strlen(namelist[i]->d_name))*sizeof(char));
  46.     strcpy(tmp, chemin);
  47.     tmp[len] = '\0';
  48.     strcat(tmp, namelist[i]->d_name);
  49.     if(is_directory(tmp)) {
  50.       printf("%s\n", tmp);
  51.       arbo2(tmp);
  52.     }
  53.     else {
  54.       printf("\t%s\n", tmp);
  55.     }
  56.     //free(namelist[i]);
  57.     //free(tmp);
  58.   }
  59.   //free(namelist);
  60.   //free(chemin);
  61. }
  62. int main (int argc, char* argv[]) {
  63.   arbo2(argv[1]);
  64.   return 0;
  65. }


 
Vous voyez, là je mets en commentaire mes "free()".
Merci pour votre aide.

Reply

Marsh Posté le 23-01-2004 à 02:33:48   

Reply

Marsh Posté le 23-01-2004 à 02:38:26    

len = strlen(racine);
      chemin = (char*) malloc((len+1)*sizeof(char));
      strcpy(chemin, racine);
      chemin[len] = '\0';  
 
 
=>
 
chemin = strdup(racine)
 
rgarderais le reste demain si personne a fait

Reply

Marsh Posté le 23-01-2004 à 02:40:41    

OK, mais c'est sûr qu'il n'y aura pas de merdes avec ça ?
-> genre avec l'emplacement de '\0' car j'ai lutté aussi pour ça..

Reply

Marsh Posté le 23-01-2004 à 03:27:04    

Pourquoi les gens qui apprennent à programmer en C n'apprennent jamais à utiliser un debugger ? Tu compiles ton programme en -g, tu le lances, il segfault et tu récupère un dump. Tu lances le debugger et hop, tu vois ou ça plante... Un segfault c'est généralement un des trucs les plus simple à debugger... Avec un debugger.

Reply

Marsh Posté le 23-01-2004 à 11:29:04    

Voici un truc pour te simplifier la vie. Utilises Valgrind s'il est dispo pour ta plateforme et essaye aussi efence http://freshmeat.net/projects/efence/?topic_id=47

Reply

Marsh Posté le 23-01-2004 à 12:09:49    

Code :
  1. for (i=0; i<n; i++) {
  2.           tmp = (char*) malloc((len+strlen(namelist[i]->d_name))*sizeof(char));
  3.           strcpy(tmp, chemin);
  4.           tmp[len] = '\0';
  5.           strcat(tmp, namelist[i]->d_name);
  6.      
  7.           if(is_directory(tmp)) {
  8.               printf("%s\n", tmp);
  9.               arbo2(tmp);
  10.           }


 
ton malloc est un caractere trop court:
tmp = (char*) malloc((len+strlen(namelist[i]->d_name)+1)*sizeof(char));
Tu n'as pas la place pour le \0 final de chaine.
 
Le fait que ca plante pas systematiquement vient probablement du fait que pour des raisons d'alignement memoire, comme tu ne depasses que d'un octet, tu as des chances que l'octet de trop soit dans une zone non allouee pour quelque chose d'autre.
 
A+,


Message édité par gilou le 23-01-2004 à 12:12:32

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-01-2004 à 12:34:34    

Et si  tu veux optimiser un poil, tu calcules d'abord la taille max de ta variable tmp, et tu fais l'allocation une fois pour toute.
 

Code :
  1. j = 0;
  2. for (i=0; i<n; i++)
  3.   if (j < strlen(namelist[i]->d_name))
  4.     j = strlen(namelist[i]->d_name);
  5. }
  6. tmp = malloc(len + j + 1); 
  7. for (i=0; i<n; i++)
  8.   *tmp = 0;
  9.   strcpy(tmp, chemin); 
  10.   strcat(tmp, namelist[i]->d_name); 
  11.   /* ..... */
  12. }
  13. free(tmp);


 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-01-2004 à 12:47:12    

1) utilise electric-fence
2) pas de 2

Reply

Marsh Posté le 23-01-2004 à 22:39:20    

gilou a écrit :

Code :
  1. for (i=0; i<n; i++) {
  2.           tmp = (char*) malloc((len+strlen(namelist[i]->d_name))*sizeof(char));
  3.           strcpy(tmp, chemin);
  4.           tmp[len] = '\0';
  5.           strcat(tmp, namelist[i]->d_name);
  6.      
  7.           if(is_directory(tmp)) {
  8.               printf("%s\n", tmp);
  9.               arbo2(tmp);
  10.           }


 
ton malloc est un caractere trop court:
tmp = (char*) malloc((len+strlen(namelist[i]->d_name)+1)*sizeof(char));
Tu n'as pas la place pour le \0 final de chaine.
 
Le fait que ca plante pas systematiquement vient probablement du fait que pour des raisons d'alignement memoire, comme tu ne depasses que d'un octet, tu as des chances que l'octet de trop soit dans une zone non allouee pour quelque chose d'autre.
 
A+,


 
D'où l'intérêt d'utiliser strdup comme il a été signalé plus haut, d'autant que l'opération de sauvegarde dans une chaîne temporaire apparait deux fois dans le code, donnant lieu à des allocations compliquées.


Message édité par el muchacho le 23-01-2004 à 22:50:27
Reply

Marsh Posté le 23-01-2004 à 22:39:20   

Reply

Marsh Posté le 23-01-2004 à 22:58:46    

(char*) malloc((len+strlen(namelist[i]->d_name))*sizeof(char));
 
 
wow
 
malloc(len+strlen(namelist[i]->d_name));
 
suffit amplement
 
t'as le morceau pour l''\0' ? la mise à 0 n'est pas nécessaire après un strcpy


Message édité par Taz le 23-01-2004 à 22:58:52
Reply

Marsh Posté le 23-01-2004 à 23:27:14    

el muchacho a écrit :


 
D'où l'intérêt d'utiliser strdup comme il a été signalé plus haut, d'autant que l'opération de sauvegarde dans une chaîne temporaire apparait deux fois dans le code, donnant lieu à des allocations compliquées.


Oui sauf que non: ca se voit pas dans mon extrait de son code, mais il fait un ajout de chaine au bout de celle dupliquée.
Donc il faut passer par un malloc...
 
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-01-2004 à 23:28:07    

j'adore asprintf :o

Reply

Marsh Posté le 26-01-2004 à 00:41:09    

Merci pour vos remarques.
Dsl mais je n'ai pas pu les consulter plus tôt et je vais
regarder tout ça et vous en dire plus.
Merci à vous.

Reply

Marsh Posté le 27-01-2004 à 10:35:18    

gilou a écrit :


 
ton malloc est un caractere trop court:
tmp = (char*) malloc((len+strlen(namelist[i]->d_name)+1)*sizeof(char));
Tu n'as pas la place pour le \0 final de chaine.
 
Le fait que ca plante pas systematiquement vient probablement du fait que pour des raisons d'alignement memoire, comme tu ne depasses que d'un octet, tu as des chances que l'octet de trop soit dans une zone non allouee pour quelque chose d'autre.
 
A+,


 
Oui, c'est effectivement cela qui me faisait plantait aléatoirement, et aussi l'autre malloc que je faisais où il manquait ausi une case mémoire :

Code :
  1. chemin = (char*) realloc(chemin, (len+1)*sizeof(char));


J'ai mis len+2 et c'et OK.
 
C'était vraiment pas évident du fait qu'il marchait correctement de temps en temp.. Le débuggueur ne m'avait pas aidé et c'est pour ça que j'avais posté.
Merci bien !
 

Reply

Marsh Posté le 27-01-2004 à 12:32:23    

se comme sizeof(char)==1 par définition ...

Reply

Marsh Posté le 27-01-2004 à 19:56:00    

Oui, bien entendu mais les profs sont galère avec ça..
Histoire que l'on n'oublie pas!

Reply

Marsh Posté le 27-01-2004 à 19:57:39    

ben si vous l'oublié, si c'était clair dans vos têtes ...

Reply

Marsh Posté le 27-01-2004 à 23:22:25    

Ndmax a écrit :


 
Oui, c'est effectivement cela qui me faisait plantait aléatoirement, et aussi l'autre malloc que je faisais où il manquait ausi une case mémoire :

Code :
  1. chemin = (char*) realloc(chemin, (len+1)*sizeof(char));


J'ai mis len+2 et c'et OK.
 
C'était vraiment pas évident du fait qu'il marchait correctement de temps en temp.. Le débuggueur ne m'avait pas aidé et c'est pour ça que j'avais posté.
Merci bien !
 
 


Un plantage aleatoire est presque toujours deterministe :D
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed