Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
5957 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Segmentation fault aléatoires !!

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Segmentation fault aléatoires !!

n°619651
ndmax
Posté le 23-01-2004 à 02:33:48  profilanswer
 

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.

mood
Publicité
Posté le 23-01-2004 à 02:33:48  profilanswer
 

n°619653
chrisbk
-
Posté le 23-01-2004 à 02:38:26  profilanswer
 

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

n°619655
ndmax
Posté le 23-01-2004 à 02:40:41  profilanswer
 

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..

n°619659
matafan
Posté le 23-01-2004 à 03:27:04  profilanswer
 

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.

n°619669
black_lord
Truth speaks from peacefulness
Posté le 23-01-2004 à 07:43:42  profilanswer
 
n°619924
Kristoph
Posté le 23-01-2004 à 11:29:04  profilanswer
 

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

n°619998
gilou
Modérateur
Modosaurus Rex
Posté le 23-01-2004 à 12:09:49  profilanswer
 

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! --  Le capitaine qui ne veut pas obéir à la carte finira par obéir aux récifs. -- Il ne faut plus dire Sarkozy, mais Sarkozon -- (╯°□°)╯︵ ┻━┻
n°620024
gilou
Modérateur
Modosaurus Rex
Posté le 23-01-2004 à 12:34:34  profilanswer
 

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! --  Le capitaine qui ne veut pas obéir à la carte finira par obéir aux récifs. -- Il ne faut plus dire Sarkozy, mais Sarkozon -- (╯°□°)╯︵ ┻━┻
n°620034
Taz
bisounours-codeur
Posté le 23-01-2004 à 12:47:12  profilanswer
 

1) utilise electric-fence
2) pas de 2

n°620644
el muchach​o
Comfortably Numb
Posté le 23-01-2004 à 22:39:20  profilanswer
 

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
mood
Publicité
Posté le 23-01-2004 à 22:39:20  profilanswer
 

n°620656
Taz
bisounours-codeur
Posté le 23-01-2004 à 22:58:46  profilanswer
 

(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
n°620681
gilou
Modérateur
Modosaurus Rex
Posté le 23-01-2004 à 23:27:14  profilanswer
 

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! --  Le capitaine qui ne veut pas obéir à la carte finira par obéir aux récifs. -- Il ne faut plus dire Sarkozy, mais Sarkozon -- (╯°□°)╯︵ ┻━┻
n°620682
Taz
bisounours-codeur
Posté le 23-01-2004 à 23:28:07  profilanswer
 

j'adore asprintf :o

n°621555
ndmax
Posté le 26-01-2004 à 00:41:09  profilanswer
 

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.

n°622562
ndmax
Posté le 27-01-2004 à 10:35:18  profilanswer
 

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 !
 

n°622705
Taz
bisounours-codeur
Posté le 27-01-2004 à 12:32:23  profilanswer
 

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

n°623013
ndmax
Posté le 27-01-2004 à 19:56:00  profilanswer
 

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

n°623015
Taz
bisounours-codeur
Posté le 27-01-2004 à 19:57:39  profilanswer
 

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

n°623250
gilou
Modérateur
Modosaurus Rex
Posté le 27-01-2004 à 23:22:25  profilanswer
 

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! --  Le capitaine qui ne veut pas obéir à la carte finira par obéir aux récifs. -- Il ne faut plus dire Sarkozy, mais Sarkozon -- (╯°□°)╯︵ ┻━┻

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Segmentation fault aléatoires !!

 

Sujets relatifs
bug de ASP - SQL serveur ?? tabulations et espaces aléatoires...drole de segmentation fault (urgent)
Question sur les nombre aléatoires...[C] fread -> segmentation fault
Signal Handler (segmentation fault)Erreur de segmentation :/
Comment obtenir des nombres aléatoires mais seulement des entiers ? 
Plus de sujets relatifs à : Segmentation fault aléatoires !!


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)