2012-04-12 6 views
5

Ich bin sehr neu in C und kann nicht herausfinden, was mit dem folgenden Code falsch ist.Adresse 0x0 ist nicht Stack'd, Malloc'd oder (kürzlich) frei

int main() { 
    char filen[] = "file.txt"; 
    FILE *file = fopen (filen, "r"); 
    if (file != NULL) 
    { 
     char line [ 128 ]; 
     while (fgets (line, sizeof line, file) != NULL) /* read a line */ 
     { 
      int i; 
      char *result; 
      for(i=0; i< NUM;i++) 
      { 
       char *rep; 
       rep = (char *) malloc (sizeof(mychars[i][0])); 
       strcpy(rep, mychars[i][0]); 
       char *with; 
       with = (char *) malloc (sizeof(mychars[i][1])); 
       strcpy(with, cgichars[i][1]); 
       result = (char *) malloc (sizeof(char) * 128); 
       result = str_replace(line, rep, with); 
      } 


      fputs(result, stdout); 
     } 
    } 
    fclose (file); 


    return 0; 
} 

Valgrind gibt mir diese Fehlermeldung:

==4266== Invalid read of size 1 
==4266== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==4266== by 0x5118A8D: fputs (iofputs.c:37) 
==4266== by 0x400A0F: main (repl.c:35) 
==4266== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

repl.c entspricht die Linie mit fputs gegen Ende dieses Codes beginnen.

Auch mychars ist ein zweidimensionales Array, das wie folgt aussieht:

char *mychars[NUM][2] = { 
    "a", "97", 
    "b", "98", 
    .... 

Kann mir bitte jemand sagen, wie dieses Problem beheben? Auch irgendwelche Hinweise darauf, wie ich meinen aktuellen Code verbessern sollte (besonders bei malloc), wären sehr willkommen.

Edit:-Code für str_replace

char *str_replace(char *str, char *orig, char *rep) { 
    char buffer[4096]; 
    char *p; 

    if(!(p = strstr(str, orig))) 
    return NULL; 

    strncpy(buffer, str, p-str); 
    buffer[p-str] = '\0'; 
    sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); 

    return buffer; 

} 

EDIT 2 Neuer Code für str_replace und Haupt

Zu Testzwecken habe ich meine str_replace Methode mit dem hier ersetzt:

What is the function to replace string in C?

A nd mein Haupt leicht geändert:

int main() { 
    static const char filen[] = "file.txt"; 
    FILE *file = fopen (filen, "r"); 
    if (file != NULL) 
    { 
     char line [ 128 ]; 
     while (fgets (line, sizeof line, file) != NULL) /* read a line */ 
     { 
      int i; 
      char *result; 
      for(i=0; i< NUM;i++) 
      { 
       char *rep; 
       rep = (char *) malloc (sizeof(mychars[i][0])); 
       strcpy(rep, mychars[i][0]); 
       char *with; 
       with = (char *) malloc (sizeof(mychars[i][1])); 
       strcpy(with, mychars[i][1]); 
       result = str_replace(line, rep, with); 
      } 


      fputs(result, stdout); 
     } 
    } 
    fclose (file); 


    return 0; 
} 

Aber ich bin immer noch

==6730== Invalid read of size 1 
==6730== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==6730== by 0x5118A8D: fputs (iofputs.c:37) 
==6730== by 0x400995: main (repl.c:29) 
==6730== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

Vielleicht ist die frustrierende Teil davon ist nicht zu wissen, was diese Ungültige Lesefehler sind.

 int i; 
     char* result; 
     result = &line[0]; 
     for(i=0; i< NUM_CGICHARS;i++) 
     { 
      char *rep; 
      rep = (char *) malloc (sizeof(char)); 
      strcpy(rep, cgichars[i][1]); 
      char *with; 
      with = (char *) malloc (sizeof(char)*3); 
      strcpy(with, cgichars[i][0]); 
      result = str_replace(result, rep, with); 
      fputs(result, stdout); 
      free(rep); 
      free(with); 
     } 

Und jetzt Ausgabe zu erhalten Ich fange an:

EDIT 3 Ich habe den Code in der Mitte des for-Schleife als solche aktualisiert! Doch nach nur zwei Iterationen, erhalte ich einen Segmentation Fault, mit valgrind mir eine ganze Reihe von dieser Angabe:

==9130== Invalid read of size 1 
==9130== at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284) 
==9130== by 0x5118A8D: fputs (iofputs.c:37) 
==9130== by 0x4009DF: main (teststep1.c:27) 
==9130== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

Antwort

5

In diesen beiden Linien

  result = (char *) malloc (sizeof(char) * 128); 
      result = str_replace(line, rep, with); 

Sie ersten Platz zuweisen für result, die Sie dann lose unmittelbar nach indem sie sie mit der Rückkehr von str_replace überschrieben werden.Diese Funktion gibt wahrscheinlich 0 zurück, sodass Ihre fputs fehlschlägt.

BTW, nicht die Rückkehr von malloc werfen, in C ist dies überflüssig und kann die Tatsache verbergen, dass Sie vergessen haben, den Prototyp einzuschließen.

Bearbeiten: Ihre str_replace Funktion ist völlig falsch in der Speicherbehandlung. Geben Sie den Zeiger nie auf eine lokale Variable zurück, der Speicherplatz ist nicht gültig, nachdem Sie die Funktion verlassen haben.

+0

Jens, danke, aber ich habe immer noch keine Idee, wie ich das beheben kann. Code für str_replace über – varatis

+0

@varatis, für 'str_replace' siehe meine Bearbeitung. Für die Logik Ihres Programms fällt es mir schwer zu verstehen, was Sie erreichen möchten. Warum ordnest du etwas innerhalb der Schleife zu, das du dann löschst, und wo du nur den letzten zugewiesenen Wert in den 'fputs' verwendest? –

+0

Ich versuche, eine Datei Zeile für Zeile zu lesen, und für jede Zeile, bestimmte Zeichen dieser Zeile mit Zeichenfolgen von Mychars angegebenen – varatis

0

Wenn NUM 0 ist, dann result nicht initialisiert ist und sein kann 0 zufällig.

Sie überprüfen nicht die Ergebnisse Ihrer Anrufe an malloc(), daher kann ein Fehler bedeuten, dass Sie versuchen, auf einen Zeiger NULL zu schreiben.

Wo ist mychars deklariert?

+0

Sie sind beide in einer "mychars.h" -Datei deklariert, die importiert wird. Aber ich habe auch bemerkt, dass das funktioniert, außer wenn ich str_replace einschließe ... Ich werde fortfahren und diesen Code hinzufügen – varatis

+0

'malloc',' NULL' zurückzugeben, ist heutzutage sehr selten, besonders bei Betriebssystemen, die Speicherüberkomprimierung implementieren . – dreamlax

+0

@dreamlax: wtf !? – James

0

Sie zeigen nicht, wie mychars deklariert wird, aber diese Zeile:

rep = (char *) malloc (sizeof(mychars[i][0])) 

wie es nur wahrscheinlich ordnet ein Byte aussieht. Außerdem reservieren Sie viel Speicherplatz und befreien ihn nie. Und hier:

result = (char *) malloc (sizeof(char) * 128); 
result = str_replace(line, rep, with); 

Sie weisen Speicher malloc und anschließend vollständig den Zeiger auf diesen Speicher verwerfen, indem Sie den Rückgabewert einer anderen Funktion über den oberen Teil zuweisen.

+0

dreamlax, nochmal, vielen Dank für deine Hilfe, aber wie repariere/verändere ich das? – varatis