2016-03-29 19 views
-1

Ich schreibe ein Programm in C, das eine Zahl in einem char * namens "Vorlage" durch eine Zeichenfolge ersetzt, aber ich bekomme ständig eine Segmentation Fault: 11 Fehler.Segmentation Fault: 11 in C

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

char *rep_str(const char *s, const char *old, const char *new1){ 
    char *ret; 
    int i, count = 0; 
    int newlen = strlen(new1); 
    int oldlen = strlen(old); 

    for (i = 0; s[i] != '\0'; i++){ 
     if (strstr(&s[i], old) == &s[i]){ 
      count++; 
      i += oldlen - 1; 
     } 
    } 
    ret = (char*)malloc(i + count * (newlen - oldlen)); 
    if (ret == NULL) 
     exit(EXIT_FAILURE); 
    i = 0; 
    while (*s){ 
     if (strstr(s, old) == s){ //compare the substring with the newstring 
      strcpy(&ret[i], new1); 
      i += newlen; //adding newlength to the new string 
      s += oldlen;//adding the same old length the old string 
     } else { 
     ret[i++] = *s++; 
     } 
    } 
    ret[i] = '\0'; 

    return ret; 
} 

char* madlib_by_numbers(char* temp, int word_count, char* words[]){ 
    char* numbers[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; 
    int tempSize = strlen(temp); 

    for (int i = 0; i < tempSize; i++){ 
     if (isdigit(temp[i])){ 
      for (int j = 0; j < (sizeof(numbers)/sizeof(char*)); j++){ 
       temp = rep_str(temp, numbers[j], words[j]); //it makes it to this line, but never gets to assert() 
      } 
     } 
    } 

    return temp; 
} 

int main() { 
    char* temp1 = "The 1 0 likes to 2 in the moonlight."; 
    char* words[] = {"git", "brilliant", "swim"}; 
    char* result = "The brilliant git likes to swim in the moonlight."; 
    int stringLength = strlen(result); 

    char* test = madlib_by_numbers(temp1, 3, words); 
    assert(strncmp(test, result, stringLength) == 0); 
    free(test); 

    return 0; 
} 

und als ich den Debugger ausführen, heißt es einfach: Segmentation Fault: 11

Was ich möchte nur verstehen, wo die Segmentation fault Fehler herkommt, habe ich den Verdacht einer meiner Schleifen zu läuft viele Male.

+2

Aber wo ist Ihr 'main()' Funktion? –

+0

** Woher ** erhalten Sie diesen Fehler? Was sagt der Debugger? – Olaf

+0

@Olaf macht es zu "temp = rep_str (temp, Zahlen [j], Wörter [j])" und ich bekomme das korrekte Ergebnis, aber dann bekomme ich den Segmentation Fault Fehler und es macht es niemals zu assert() in mein Haupt. – Teecolz

Antwort

0
ret = (char*)malloc(i + count * (newlen - oldlen)); 

Es gibt ein paar Probleme mit dieser Codezeile.

  • Für einen Start, don't cast malloc (oder jede void *, die Sie auf eine Variable verschiedener Zeigertyp sind zuweisen oder umgekehrt).
  • Wenn Sie beabsichtigen, Speicherplatz zum Speichern einer Zeichenfolge zu reservieren, wo wird die Zeichenfolge beendet '\0' gehen? Sie müssen wissen, dass dies für eine leere old Zeichenfolge malloc(0) ist und Null Bytes nicht ausreicht, um eine leere Zeichenfolge zu speichern.
  • Es gibt auch ein Problem, wenn Sie, dass old erwarten ein Teil von new sein kann (zum Beispiel, sind Sie "0" mit "hell0" ersetzen). Sie müssen Ihren Algorithmus anpassen, um dieses Problem zu lösen. Ich werde das als eine Herausforderung für Sie hinterlassen :)

for (int i = 0; i < tempSize; i++){ 
    if (isdigit(temp[i])){ 
     for (int j = 0; j < (sizeof(numbers)/sizeof(char*)); j++){ 
      temp = rep_str(temp, numbers[j], words[j]); //it makes it to this line, but never gets to assert() 
     } 
    } 
} 

users previous answer hervorgehoben diesen Code richtig versuchen, aber nicht aus dem richtigen Grund ... und so die Lösung, die er/sie präsentiert wird falsch.

isdigit(temp[i]) may also cause segfaults for some inputs. Ich empfehle stattdessen isdigit((unsigned char) temp[i]), in diesem Fall.

Es ist nicht zulässig, auf words[j] zuzugreifen, wenn word_count 3 ist und j größer oder gleich 3 ist; Sie greifen auf dieses Array außerhalb der Grenzen zu.

Sie müssen auch zu free jeder Speicher Sie *alloc (während sie gleichzeitig nicht free ing Speicher, dass Sie nicht *alloc) vorsichtig sein.Das vorherige zu vergessen führt nicht zu Abstürzen, aber Ihr Programm wird nicht glücklich laufen; Es wird Heaps des Speichers verwendet.

Betrachten wir so etwas statt:

temp = strdup(temp); 
if (temp == NULL) { 
    exit(EXIT_FAILURE); 
} 
for (int i = 0; i < tempSize; i++){ 
    if (isdigit((unsigned char) temp[i])){ 
     for (int i = min(word_count, sizeof(numbers)/sizeof(char*)), j = 0; j < i; j++){ 
      char *new = rep_str(temp, numbers[j], words[j]); 
      free(temp); 
      temp = new; 
     } 
    } 
} 
1

Es gibt ein paar Probleme mit Ihrem Code. Allerdings ist die direkte Antwort auf Ihre Frage in dieser Schleife:

for (int j = 0; j < (sizeof(numbers)/sizeof(char*)); j++){ 
     temp = rep_str(temp, numbers[j], words[j]); 
} 

Du rep_str für jede Ziffer aufrufen, während Sie bedeuten nennen rep_str nur dann, wenn die Ziffer in temp die entsprechende Ziffer in numbers entspricht. Fügen Sie also dieses bedingte if(strcmp(temp,numbers[j]) == 0) direkt vor der Zeile temp=... hinzu. Dann löst es Ihr aktuelles Problem.

Der Segfault wird verursacht, weil das Array words nur aus drei Elementen besteht. Ihre alte Schleife indiziert von 0 bis 9 und schlägt fehl, wenn j=3, out of bound.

Löschen Sie auch die free() am Ende Ihres Programms. test wurde nie zugewiesen und verursacht einen Core-Dump.

+0

'rep_str()' gibt das Ergebnis eines 'malloc()' zurück, das möglicherweise verloren geht, wenn 'temp' mehr als einmal in' madlib_by_numbers() 'zugewiesen wurde. Vielleicht nennt er nicht "frei()" genug, anstatt zu viel. Der Anfangswert von 'temp' ist jedoch ein Zeichenfolgenliteral, das nicht freigegeben werden kann. – e0k