2015-11-01 3 views
-2

Я работаю над созданием программы C для реализации списков в двоичном файле, и после компиляции я получил ошибку сегментации. Это мой код:Ошибка сегментации в C

#include <stdio.h> 

#include <string.h> 

#include <stdlib.h> 


#define LONG_NP 30 

struct Personne { 

    char nomPre[LONG_NP+1]; 

    char sexe ; 

    float taille, poids ; 

}; 


struct Elem { 

    struct Personne pers ; 

    struct Elem * suivant ; 

}; 


typedef struct Elem * pointeur ; 
typedef struct Elem Element; 

void lire(FILE * aLire, struct Personne * P) { 

    struct Personne unePers ; 

    fgets(unePers.nomPre, LONG_NP+1, aLire) ; 

    fscanf(aLire,"%c%f%f\n", &unePers.sexe, &unePers.taille, 

        &unePers.poids); 

    *P = unePers; 

} 



void creerFIFO(pointeur * P) { 



    pointeur laListe = NULL, tempo, presentement; 



    FILE * aLire = fopen("metrique.tp3", "r"); 

    while (! feof(aLire)) { 

     tempo = (pointeur) malloc (sizeof (struct Elem)); 

     lire(aLire, &tempo->pers); 

     if (laListe == NULL) 

       laListe = tempo ; 

     else 

       presentement->suivant = tempo; 



     presentement = tempo; 

    } 

    fclose(aLire); 

    if (laListe) presentement->suivant = NULL; 

    *P = laListe; 

} 



void afficher(pointeur liste, char ordre[]) { 

    printf("Contenu de la liste en ordre %s\n", ordre); 

    while (liste) { 

     printf("%s %c % 7.2f %8.1f\n", liste->pers.nomPre, 

      liste->pers.sexe, liste->pers.taille, liste->pers.poids); 

     liste = liste->suivant; 

    } 

} 



void creerBinaire(pointeur liste, char * nomFile) { 

    FILE * aCreer = fopen(nomFile, "wb"); 

    int nbOctets = sizeof(struct Personne); 

    if(!aCreer) 
     printf("Fichier pas ouvert\n"); 

    while (liste) { 

     fwrite(&liste->pers, nbOctets, 1, aCreer); 

     liste = liste->suivant; 

    } 

    fclose(aCreer); 

    printf("Fin de la creation du fichier binaire\n"); 

} 



void relire(char nomFile[]) { 

     FILE * aLire = fopen(nomFile, "rb"); 

     struct Personne unePers ; 

     int rang = 0, nbOctets = sizeof(struct Personne); 



     while (fread(&unePers, nbOctets, 1, aLire), !feof(aLire)) 

      printf("%2d) %s %c % 7.2f %8.1f\n", ++rang, 

       unePers.nomPre, unePers.sexe, unePers.taille, 

        unePers.poids); 



     fclose(aLire); 



} 




/* écrivez vos fonctions ici avec, en commentaires, le numéro de la 
    question de l'examen à laquelle elles répondent. 
*/ 


/* Question 6 */ 

void chercherNom(pointeur Liste, pointeur *Av, pointeur *CL, char Nom[]) 
{ 

    pointeur Avant = NULL; 
    int trouve = 0; 
    while (Liste && !trouve) 
    { 
     if(strcmp(Nom, Liste->pers.nomPre)!=0) 
     { 
      Avant = Liste; 
      Liste = Liste->suivant; 
     } 
     else 
      trouve = 1; 
    } 

    *Av = Avant; 
    *CL = Liste; 
} 


void Changer(struct Personne * A, struct Personne B) 
{ 
     struct Personne Tempo = *A; 

     if(strcmp(Tempo.nomPre, B.nomPre) !=0) 
     strcpy(Tempo.nomPre, B.nomPre); 

     if(B.sexe != ' ') 
      Tempo.sexe = B.sexe; 

     if(B.taille > 0) 
      Tempo.taille = B.taille; 

     if(B.poids >0) 
      Tempo.poids = B.poids; 

     *A = Tempo; 

} 





void cherModif(pointeur Liste, char Nom[], struct Personne Pers) 
{ 

    pointeur Avant, CL; 
    struct Personne Tempo; 


    chercherNom(Liste,&Avant, &CL,Nom); 

    if(CL) 
    { 
     Tempo = CL->pers; 
     printf("trouve %s\n",Tempo.nomPre); 
     Changer(&Tempo,Pers); 
     CL->pers = Tempo; 
    } 
    else 
     printf("pas trouve %s\n",Nom); 
} 



void CreerLIFO(pointeur Liste, pointeur *P, char sexevoulu) 
{ 
    pointeur L = NULL; 
    pointeur Tempo; 


    while(Liste) 
    { 
     if(Liste->pers.sexe == sexevoulu) 
     { 

      Tempo = (Element *) malloc(sizeof(Element)); 

      Tempo->pers = Liste->pers; 


      Tempo->suivant = L; 

      L = Tempo; 

     } 


     Liste = Liste->suivant; 
    } 




    *P = L; 
} 



void main() { 

/* Écrivez les déclarations des 2 nouvelles listes ici */ 
    pointeur ListeF, ListeM ; 


    pointeur liste ; 

    /* question 6 */ 

    struct Personne Tempo; 
    char NomTempo[LONG_NP+1]; 
    creerFIFO(&liste); 

    afficher(liste, "FIFO"); 

    /* Écrivez les appels de la fonctions de la 
     question 6 ici, le bon résultat sera observé 
     avec la relecture de metrique.bin 
    */ 


    strcpy(Tempo.nomPre,"BEDARD MARC-ANDRE    "); 
    Tempo.sexe = 'M'; 
    Tempo.taille = 1.54; 
    Tempo.poids = 0; 

    cherModif(liste,Tempo.nomPre,Tempo); 

    strcpy(NomTempo,"TREMBLAY CYLVAIN    "); 

    strcpy(Tempo.nomPre,"TREMBLAY SYLVAIN    "); 
    Tempo.sexe = ' ' ; 
    Tempo.taille = 0; 
    Tempo.poids = 0; 

    cherModif(liste,NomTempo,Tempo); 




    creerBinaire(liste, "metrique.bin"); 

    relire("metrique.bin"); 


    /* Écrivez les appels pour la question 7 ici */ 

    CreerLIFO(liste,&ListeF,'F'); 
    CreerLIFO(liste,&ListeM,'M'); 




    /* Pour tester, écrivez 2 appels de la fonction 
     afficher : */ 
     afficher(ListeF,"LIFO"); 
     afficher(ListeM,"LIFO"); 

} 

Я использую GCC как компилятор, и я не получил какую-либо вины с компиляцией, возникает проблема, когда я пытался возбудить файл вывод с помощью команды ./a .out и здесь я получил Fault без каких-либо спецификаций. Итак, вопрос в том, как решить проблему с сегментацией, потому что я еще не вижу ее в коде.

Теперь после отладки я нахожу это:

Starting program: /root/a.out 

Breakpoint 1, main() at /root/Desktop/tp/liste.c:282 
282 creerFIFO(&liste); 
(gdb) s 
creerFIFO (P=0x7fffffffe2d8) at /root/Desktop/tp/liste.c:54 
54  pointeur laListe = NULL, tempo, presentement; 
(gdb) s 
58  FILE * aLire = fopen("metrique.tp3", "r"); 
(gdb) s 
60  while (! feof(aLire)) { 
(gdb) s 

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7aa4230 in feof() from /lib/x86_64-linux-gnu/libc.so.6 

Это означает, что у меня возникли проблемы с функцией в то время как

+2

Где вы получите ошибку Сегментация Fault?Пожалуйста, отметьте более или менее, где это происходит, поэтому будущим пользователям не нужно читать _all_ кода и вместо этого просто более важные части. – Arc676

+1

В чем вопрос? – fuz

+0

Я использую GCC в качестве компилятора, и у меня не было никакой ошибки в компиляции, проблема возникает, когда я пытался возбудить выходной файл с помощью команды ./a.out, и здесь я получил Fault без каких-либо спецификаций , –

ответ

0

Я подозреваю, что ваш файл * aLire является nullptr

Вы должны проверьте возвращаемое значение fopen перед его использованием для feof. Когда я пытаюсь запустить свой код, я вижу ошибку, похожую на вашу, потому что у меня нет файла «metrique.tp3» в моей системе. У вас есть один (и на том же пути, что и исполняемый файл, который вы пытаетесь запустить)?

Я не собираюсь вас обидеть, но из вашего кода я думаю, что вы не сделали много кодирования. По крайней мере, не в C/C++. Некоторые указатели, которые могут вам помочь:

  1. Проверьте возвращаемые переменные системных вызовов. Вы всегда должны это делать, но особенно когда функция возвращает указатель.
  2. Всегда проверяйте, не указаны ли указатели перед их использованием.
  3. Инициализация ваших переменных. Я вижу много объявлений указателей без инициализации. Если вы не инициализируете указатель, последующая проверка, чтобы увидеть, является ли он нулевым указателем, часто будет бесполезной, поскольку указатель, вероятно, получит случайное значение.
  4. Если вы выделяете память (malloc, calloc и т. Д.), Вы должны освободить ее, как только вы закончите с ней. Я вижу malloc() в вашем коде, но я не вижу свободного() в любом месте.
  5. Хорошая среда IDE может вам очень помочь, особенно когда вы начинаете кодирование. Если вы запустите этот исполняемый файл в отладчике, он покажет вам, где именно произошла ваша ошибка сегментации, и вы сможете просмотреть содержимое всех ваших переменных. В этом случае это немедленно указывало бы вам на то, что aLire является нулевым указателем. Я не уверен, на какой платформе вы работаете. Для окон есть бесплатная версия визуальной студии, которая включает в себя все необходимые инструменты. Если вы находитесь на другой платформе (или просто не хотите использовать компилятор Microsoft), мне всегда нравилось работать с CDT Eclipse, но прошло несколько лет с тех пор, как я работал с этим, поэтому он, возможно, был заменен другим Иды.
  6. Наконец, вы, конечно, можете свободно использовать любой язык, который вам нужен, но если вы используете английский для своих имен переменных и функций, нам не-французам намного легче понять, каковы ваши намерения и, следовательно, помочь вы.
-1

Я изменил немного функцию lire(), теперь работает правильно

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 


#define LONG_NP 30 

struct Personne { 

    char nomPre[LONG_NP+1]; 

    char sexe ; 

    float taille, poids ; 

}; 


struct Elem { 

    struct Personne pers ; 

    struct Elem * suivant ; 

}; 


typedef struct Elem * pointeur ; 
typedef struct Elem Element; 

/*___________________________________________________________________ 
*/ 
void lire(FILE * aLire, struct Personne * p) { 

    if(!p) { 
     printf("lire: Persone *p est nulle"); 
     return; 
    } 

    fgets(p->nomPre, LONG_NP+1, aLire) ; 

    fscanf(aLire,"%c%f%f\n", 
      &(p->sexe), &(p->taille),&(p->poids)); 

} 
/*___________________________________________________________________ 
*/ 


void creerFIFO(pointeur * P) { 

    pointeur laListe = NULL, tempo, presentement; 

    FILE * aLire = fopen("metrique.tp3", "r"); 

    if(aLire) { 
     while (! feof(aLire)) { 
      tempo = (pointeur) malloc (sizeof (struct Elem)); 

      lire(aLire, &tempo->pers); 

      if (laListe == NULL) 
       laListe = tempo ; 
      else 
       presentement->suivant = tempo; 

      presentement = tempo; 
     } 

     fclose(aLire); 
    } else { 
     perror("creerFIFO"); 
    } 

    if (laListe) presentement->suivant = NULL; 

    *P = laListe; 

} 

/*___________________________________________________________________ 
*/ 

void afficher(pointeur liste, char ordre[]) { 

    printf("Contenu de la liste en ordre %s\n", ordre); 

    while (liste) { 

     printf("%s %c % 7.2f %8.1f\n", liste->pers.nomPre, 

       liste->pers.sexe, liste->pers.taille, liste->pers.poids); 

     liste = liste->suivant; 

    } 

} 


/*___________________________________________________________________ 
*/ 
void creerBinaire(pointeur liste, char * nomFile) { 

    FILE * aCreer = fopen(nomFile, "wb"); 

    int nbOctets = sizeof(struct Personne); 

    if(!aCreer) 
     printf("Fichier pas ouvert\n"); 

    while (liste) { 

     fwrite(&(liste->pers), nbOctets , 1, aCreer); 

     liste = liste->suivant; 
    } 

    fclose(aCreer); 

    printf("Fin de la creation du fichier binaire\n"); 

} 

/*___________________________________________________________________ 
*/ 

void relire(char nomFile[]) { 

    FILE * aLire = fopen(nomFile, "rb"); 

    struct Personne unePers ; 

    int rang = 0, nbOctets = sizeof(struct Personne); 


    while (fread(&unePers, nbOctets, 1, aLire), !feof(aLire)) 

     printf("%2d) %s %c % 7.2f %8.1f\n", ++rang, 
       unePers.nomPre, unePers.sexe, unePers.taille, 
       unePers.poids); 


    fclose(aLire); 

} 

/*___________________________________________________________________ 

    écrivez vos fonctions ici avec, en commentaires, le numéro de la 
    question de l'examen à laquelle elles répondent. 

    Question 6 

*/ 
void chercherNom(pointeur Liste, pointeur *Av, pointeur *CL, char Nom[]) { 

    pointeur Avant = NULL; 
    int trouve = 0; 
    while (Liste && !trouve) { 
     if(strcmp(Nom, Liste->pers.nomPre)!=0) { 
      Avant = Liste; 
      Liste = Liste->suivant; 
     } else 
      trouve = 1; 
    } 

    *Av = Avant; 
    *CL = Liste; 
} 


/*___________________________________________________________________ 
*/ 

void Changer(struct Personne * A, struct Personne B) { 
    struct Personne Tempo = *A; 

    if(strcmp(Tempo.nomPre, B.nomPre) !=0) 
     strcpy(Tempo.nomPre, B.nomPre); 

    if(B.sexe != ' ') 
     Tempo.sexe = B.sexe; 

    if(B.taille > 0) 
     Tempo.taille = B.taille; 

    if(B.poids >0) 
     Tempo.poids = B.poids; 

    *A = Tempo; 

} 



/*___________________________________________________________________ 
*/ 

void cherModif(pointeur Liste, char Nom[], struct Personne Pers) { 

    pointeur Avant, CL; 
    struct Personne Tempo; 


    chercherNom(Liste,&Avant, &CL,Nom); 

    if(CL) { 
     Tempo = CL->pers; 
     printf("trouve %s\n",Tempo.nomPre); 
     Changer(&Tempo,Pers); 
     CL->pers = Tempo; 
    } else 
     printf("pas trouve %s\n",Nom); 
} 

/*___________________________________________________________________ 
*/ 

void CreerLIFO(pointeur Liste, pointeur *P, char sexevoulu) { 
    pointeur L = NULL; 
    pointeur Tempo; 


    while(Liste) { 
     if(Liste->pers.sexe == sexevoulu) { 

      Tempo = (Element *) malloc(sizeof(Element)); 

      Tempo->pers = Liste->pers; 


      Tempo->suivant = L; 

      L = Tempo; 

     } 

     Liste = Liste->suivant; 
    } 


    *P = L; 
} 

/*___________________________________________________________________ 
*/ 

void main() { 

    /* Écrivez les déclarations des 2 nouvelles listes ici */ 
    pointeur ListeF, ListeM ; 


    pointeur liste ; 

    /* question 6 */ 

    struct Personne Tempo; 
    char NomTempo[LONG_NP+1]; 

    creerFIFO(&liste); 
    afficher(liste, "FIFO"); 

    /* Écrivez les appels de la fonctions de la 
     question 6 ici, le bon résultat sera observé 
     avec la relecture de metrique.bin 
    */ 

    strcpy(Tempo.nomPre,"BEDARD MARC-ANDRE    "); 
    Tempo.sexe = 'M'; 
    Tempo.taille = 1.54; 
    Tempo.poids = 0; 

    cherModif(liste,Tempo.nomPre,Tempo); 

    strcpy(NomTempo, "TREMBLAY CYLVAIN    "); 

    strcpy(Tempo.nomPre,"TREMBLAY SYLVAIN    "); 
    Tempo.sexe = ' ' ; 
    Tempo.taille = 0; 
    Tempo.poids = 0; 

    cherModif(liste,NomTempo,Tempo); 


    creerBinaire(liste, "metrique.bin"); 

    relire("metrique.bin"); 


    /* Écrivez les appels pour la question 7 ici */ 

    CreerLIFO(liste,&ListeF,'F'); 
    CreerLIFO(liste,&ListeM,'M'); 



    /* Pour tester, écrivez 2 appels de la fonction 
     afficher : */ 
    afficher(ListeF,"LIFO"); 
    afficher(ListeM,"LIFO"); 

} 
Смежные вопросы