2016-04-08 8 views
0

Programm:getc Funktion produziert segfault

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

char *f_gets(char *s, int n, FILE *iop) 
{ 
    int c=0; 
    char *cs; 
    cs = s; 

    while (--n > 0 && (c = getc(iop)) != EOF) 
    { 
     if ((*cs++ = c) == '\n') 
      break; 
    } 
    *cs = '\0'; 
    return (c == EOF && cs == s) ? NULL : s; 
} 


main(int argc, char *argv[]) 
{ 
    FILE *fp1,*fp2; 
    char s2[100],s1[100]; 
    if (argc <= 2) 
     printf("2 argument needed \n"); 
    else 
     if((fp1=fopen(argv[1],"r"))== NULL && (fp2=fopen(argv[2],"r"))==NULL) 
      printf("cat: can't open The file\n"); 
     else 
     { 
      while(1) 
      { 
       f_gets(s1,100,fp1); // 1st iteration 
       f_gets(s2,100,fp2); // 2nd iteration 
       if(!strcmp(s1,s2)) 
        printf("%s %s",s1,s2); 
      } 
      fclose(fp1); 
      fclose(fp2); 
     } 
} 

Ausgang:

$ ./a.out a b 
Segmentation fault (core dumped) 
$ 

In dem obigen Programm tritt der segfault, wenn wir die f_gets bei zweiten Mal anrufen. Selbst wenn ich zweimal das Programm überprüfe, ist es schwer, das Problem zu finden. Erklärt jemand, warum es das Problem erzeugt.

Antwort

8

Ihre zweite Datei ist nicht geöffnet, wenn Sie den Anruf tätigen.

Das Problem ist, dass Sie fopen vom Pfad mit Kurzschluss anrufen:

if((fp1=fopen(argv[1],"r"))== NULL && (fp2=fopen(argv[2],"r"))==NULL) 

Durch einen Fehler im Code, wenn fp1 fein öffnen, fp2 bleibt immer geschlossen. Dies liegt daran, dass (fp1=fopen(argv[1],"r"))== NULL zu 0 ausgewertet wird, und stellen Sie sicher, dass (fp2=fopen(argv[2],"r"))==NULL niemals aufgerufen wird.

Sie könnten dies beheben, indem Sie && durch || ersetzen, aber ein besserer Ansatz wäre das Öffnen einer Datei auf einmal.

2
if((fp1=fopen(argv[1],"r"))== NULL && (fp2=fopen(argv[2],"r"))==NULL) 

bedeutet, "wenn das Programm fp1 und fp2 nicht öffnen konnte". Sie könnten dies lösen, indem Sie stattdessen || verwenden. Aber schreiben Sie vorzugsweise keine langen und komplexen Ausdrücke, da sie nur eine erhöhte Chance zum Schreiben von Fehlern hinzufügen.

Stattdessen tun:

fp1=fopen(argv[1],"r"); 
if(fp1 == NULL) 
{ 
    // error handling 
} 

fp2=fopen(argv[2],"r"); 
if(fp2 == NULL) 
{ 
    fclose(fp1); 
    // error handling 
} 

Und als Bonus: Nur weil wir das Programm in ein lesbares Format neu geschrieben, wir jetzt auch einen zweiten Fehler entdeckt. Falls das Programm fp1 geöffnet, aber fp2 nicht geöffnet hat, hat es fp1 vor dem Abbrechen nie geschlossen.