[ C ] Erreur de segmentation (core dumped)

Erreur de segmentation (core dumped) [ C ] - C - Programmation

Marsh Posté le 09-11-2008 à 13:16:33    

Bonjour à tous,
 
Je suis débutant en C et je me mêle les pinceaux avec les pointeurs en ce moment. Je vous expose mon problème.
Je souhaite :
 
1 - Aller chercher dans un fichier une ligne qui contient par exemple : "etat1 etat2 etat3 e4 e5#" (espaces compris)
 
2 - Maintenant, je voudrais créer un tableau de 5 pointeurs. Chaque pointeur, pointera sur chacune des chaines de caractères. Autrement dit, si on appelle, le tableau : tab_pointeurs, on aura :
 
tab_pointeurs[0] qui pointe sur "etat1"
tab_pointeurs[1] qui pointe sur "etat2"
......
tab_pointeurs[4] qui pointe sur "e5"
 
SEULEMENT, on ne sait pas à l'avance combien d'états on aura dans le fichier, et donc de combien de pointeurs on aura besoin. Et on ne sait pas non plus quelle taille feront chaque chaine de caractères. D'où les allocations mémoires.
 
Je ne sais pas si le problème est assez clair :).
 

Code :
  1. typedef char* t_etats;
  2. 'etats' est une variable globale. Un tableau de 500 caractères maxi qui contiendra toute la ligne du fichier (espaces compris).
  3. i est la variable qui permet de se déplacer dans ce tableau.
  4. //////////////////////////////////////// FONCTION RECHERCHER_ETATS ///////////////////////////////////////////////
  5. /*   
  6. * Recherche les états de la machine dans le fichier 'machine'.
  7. * Préconditions : Le fichier existe
  8. * Postconditions : Renvoie un tableau de chaîne de caractères (les états).
  9. */
  10. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  11. t_etats* rechercher_etats(FILE* fichier){
  12.     char marqueur = '$'; t_etats* etats_ret=NULL;
  13.    
  14.     /* Parcours du fichier ligne par ligne. On sort de la boucle une fois le mot trouvé.*/
  15.     while (!feof(fichier)){
  16.          
  17.           fgets(etats,sizeof(etats),fichier);         
  18.           if(etats[0] != marqueur){
  19.                 break
  20.           } 
  21.     }
  22.     printf("Etats recherches : %s",etats);
  23.     printf("Taille : %d\n",strlen(etats)-2); // on enlève le '#' et le marqueur de fin '\0'
  24.     int unsigned i=0; int j=0; int unsigned k=0; int maxetats=0; int taille_nom_etat=0; int t=0;
  25.            
  26.     // On compte le nombre total d'états présents pour la machine. En comptant le nombre d'espace entre leurs noms et en ajoutant 1.
  27.     while(k<strlen(etats)-2){
  28.        if(etats[k]==' '){ 
  29.           maxetats++; 
  30.        }
  31.        k++;
  32.     }
  33.     maxetats++;
  34.     printf("nbre d'etats : %d\n",maxetats);
  35.     /* tab_etat est un tableau de pointeurs. Sa taille (maxetats) n'est pas connue à l'avance. Mais, on en aura besoin un peu plus haut dans la fonction  
  36.      * "indice_etat". Sa taille réelle est contenue dans la variable maxetats et on ajoute une case de plus qui contiendra toujours NULL. Cette case jouera le rôle  
  37.      * de marqueur de fin et nous permettra à l'aide d'une boucle de déterminer la taille du tableau. Les indices vont de 0 à maxetats-1. Donc, si on ajoute une  
  38.      * colonne de plus, elle aura pour indice 'maxetats'.
  39.      */
  40.     t_etats tab_etat[maxetats+1]; tab_etat[maxetats]=NULL;
  41.     for(j=0;j<maxetats;j++){
  42.  
  43.   /* On compte la taille en caracteres de chaque etat.
  44.    * strlen(mot)-2 pour éviter de prendre le dernier caractère de la chaine # et le marqueur de fin : '\0'.
  45.    */
  46.                    
  47.    while(etats[i]!=' ' && i<strlen(etats)-2){
  48.        i++;             
  49.                taille_nom_etat++;                                                                   
  50.     }
  51.     printf("taille du nom de l'etat = %d\n",taille_nom_etat);
  52.     /*
  53.      * Pour chaque état, on alloue une zone mémoire de taille variable qui contiendra son nom (chaine de caractère qui le représente). Ceci, en partant du  
  54.              * principe que les noms (des états) i.e les chaines de caractère sont de tailles différentes.
  55.      *
  56.      * Si  par exemple, nous avons les états : 'etat1' 'etat2', 'e3', 'q4', 'eta5'
  57.      * On allouera :
  58.      * Une zone mémoire de 5 caractères pour chacun des états 1 et 2.  
  59.      * Une zone de 2 caractères pour chacun des états 3 et 4 et
  60.              * Une zone de 4 caractères pour l'état 5.
  61.      * tab_etat est un tableau de pointeurs sur ces caractères. Donc,
  62.      * tab_etat[0] pointera sur l'état 1 et donc sur la chaîne : 'etat1'
  63.      * tab_etat[1] pointera sur l'état 2 et donc sur la chaîne : 'etat2'
  64.      * tab_etat[2] pointera sur l'état 3 et donc sur la chaîne : 'e2'
  65.      * tab_etat[3] pointera sur l'état 4 et donc sur la chaîne : 'q4'
  66.      * tab_etat[4] pointera sur l'état 5 et donc sur la chaîne : 'eta5'
  67.      */
  68.      tab_etat[j] = malloc(sizeof(char)*taille_nom_etat);
  69.      if(tab_etat[j]==NULL){
  70.          printf("\n Allocation Impossible \n" );
  71.          exit(EXIT_FAILURE);
  72.      }
  73.      int temp; temp = taille_nom_etat; int taille; taille = strlen(etats)-2;
  74.      if(i <= taille){
  75.           for(t=0;t<taille_nom_etat;t++){
  76.                tab_etat[j][t]=etats[i-temp];
  77.                temp--;
  78.           }
  79.       }
  80.       i++;
  81.       taille_nom_etat=0;             
  82.      }             
  83.                          
  84.      printf("Les etats sont : \n" );
  85.      for(j=0;j<maxetats;j++){
  86.           printf("%s\n",tab_etat[j]); 
  87.      }
  88.      printf("\n" );
  89.      etats_ret = tab_etat;
  90.      return etats_ret;
  91. }
  92. // Fin de la fonction rechercher_etats


 
Merci d'avance


Message édité par AigleRoyal le 10-11-2008 à 13:07:12
Reply

Marsh Posté le 09-11-2008 à 13:16:33   

Reply

Marsh Posté le 09-11-2008 à 14:25:02    

Ce sujet a été déplacé de la catégorie OS Alternatifs vers la categorie Programmation par O'gure


---------------
Relax. Take a deep breath !
Reply

Marsh Posté le 09-11-2008 à 14:47:38    

Ton code est fouilli. Decoupes ca en fonction a but restreint (lire le fichier, creer les tableaux, les remplir) tu y verras deja plus clair.

Reply

Marsh Posté le 09-11-2008 à 15:20:27    

n'utilise pas feof (ou alors lis sa documentation).
 
while(fgets(...) != NULL) est la bonne méthode.

Reply

Marsh Posté le 10-11-2008 à 09:38:09    

Ici, dans ce programme, c'est un peu fouillis, surtout parce que l'indentation est mauvaise, mais sinon la longueur n'est pas exagérée, il y a des commentaires, et l'absence de sous-fonctions n'est pas la cause du problème. Ici, dans ce programme, feof() n'est pas non plus la cause du problème.
 
Le cause est la mauvaise utilisation de la variable "i".
 

Reply

Marsh Posté le 10-11-2008 à 10:04:24    

Si tu cherchais au moins où ça plante... la valeur de i, etc. C'est le B.A.BA du débogage.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 10-11-2008 à 13:33:59    

Bonjour,
 
J'ai essayé de débugger avec gdb et je n'ai rien vu. La valeur de i ne pose pas de problèmes. Pour tester, j'ai rajouté 2 instructions au sortir de la fonction. Je rappelle qu'elle renvoit un tableau de pointeurs.
 
     tableau_etats = rechercher_etats(p_fichierM);     // où p_fichierM est un pointeur sur un fichier contenant la ligne "e1 e2 e3 e4 e5#"
 
     printf("Avant : tableau_etats[0] = %s\n",tableau_etats[0]);
     printf("Tout est OK\n" );
     printf("Apres : tableau_etats[0] = %s\n",tableau_etats[0]);
 
     Il affiche :
 
    "Avant : tableau_etats[0] = e1
     Tout est Ok
     Erreur de segmentation (core dumped)" Au lieu d'afficher "Après : tableau_etats[0] = e1"
 
Autrement dit, j'ai l'impression qu'entre deux instructions, la valeur du pointeur est supprimée ?!!! Deux instructions identiques séparées par l'affichage de "Tout est Ok" et l'une donne la bonne valeur et après, PLUS RIEN. Une erreur de segmentation.
 
J'essaie de débogger avec valgrind s'il en y a qui connaissent et je vous tiens au courant.
 
A tout à l'heure
 
AR


Message édité par AigleRoyal le 10-11-2008 à 13:35:27
Reply

Marsh Posté le 10-11-2008 à 14:11:51    

1. typedef char* t_etats;
 
45. t_etats tab_etat[maxetats+1]; tab_etat[maxetats]=NULL;
 
en fait l'erreur c'est ligne 45. Je suis surpris que ca compile en fait. Faut faire un malloc à la place d'une déclaration.


---------------
Aimer les femmes intelligentes est un plaisir de pédéraste. (Charles Baudelaire) - Vous vulgarisez :o (Jean-Kevin Dubois)
Reply

Marsh Posté le 10-11-2008 à 14:49:24    

Ok, merci Philippe. Je fais ça et je te met au parfum :)
 
Mais, quelle est réellement la différence entre un malloc d'une taille fixe et la déclaration d'un tableau de la même taille fixe ? Y a-t-il une différence en mémoire ?
 
AR

Reply

Marsh Posté le 10-11-2008 à 14:58:25    

Putain, ça marche NIIIIIIIIIIIIKKKKKKKKKKELL. Ca fait des jours que je cherche... Avec différents déboggeurs.
 
Tu m'expliques Philipe stp ?
 
Je crois qu'une fois que j'aurais compris ça, ça restera gravé à TOUT JAMAIS. Bon, alors pourquoi faire un malloc plutôt que de déclarer un tableau ?
Je suis prêt à apprendre ma leçon...
 
AR

Reply

Marsh Posté le 10-11-2008 à 14:58:25   

Reply

Marsh Posté le 10-11-2008 à 15:10:41    

Oui, il y a une différence en mémoire, c'est tout à fait ça:
malloc -> tas
déclaration -> pile ou "zone statique"
 
pour une déclaration, il faut connaitre la taille avant l'execution. Si tu veux faire une zone mémoire de taille variable, il faut faire des mallocs.


---------------
Aimer les femmes intelligentes est un plaisir de pédéraste. (Charles Baudelaire) - Vous vulgarisez :o (Jean-Kevin Dubois)
Reply

Marsh Posté le 11-11-2008 à 21:45:49    

int foo(int n)
{
   char tab[n];
   ...
}
 
 c'est tout à fait possible en C99

Reply

Marsh Posté le 11-11-2008 à 22:06:30    

Je m'en souviendrais ...


---------------
Aimer les femmes intelligentes est un plaisir de pédéraste. (Charles Baudelaire) - Vous vulgarisez :o (Jean-Kevin Dubois)
Reply

Marsh Posté le 11-11-2008 à 22:08:32    

morph a écrit :

int foo(int n)
{
   char tab[n];
   ...
}
 
 c'est tout à fait possible en C99


 
Possible, mais je ne sais pas ce qui leur est passé par la tête pour nous pondre les VLA. Probablement une grosse pierre.
 
Mise en situation :
- n est négatif > plantage
- n est abusivement grand > plantage
- problème d'allocation > impossible de le savoir
 
Bref, les VLA, c'est pas une bonne idée je trouve. :/

Reply

Marsh Posté le 11-11-2008 à 23:02:00    

Sachant que 'abusivement grand' ca commence à 1024 double :E

Reply

Marsh Posté le 11-11-2008 à 23:15:17    

Juste pour ma culture VLA, c'est l'acronyme de quoi ? (le 'L' et 'A', j'imagine que c'est Local Allocation)

Reply

Marsh Posté le 11-11-2008 à 23:33:23    

Variable-Length Array.

Reply

Marsh Posté le 12-11-2008 à 07:45:16    

ok, merci

Reply

Sujets relatifs:

Leave a Replay

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