2012-03-25 16 views
0

Ich mache einen Makefile Creator, aber ich bin in diesem Fehler auf Sprintf stecken, ist die kurioseste Sache, dass ich mehrere Sprintf vor dem einen mit dem Fehler haben und sie funktionieren gut.Segmentation Fault mit Sprintf

Hier ist der Code:

if (WIFEXITED(stat) ){ 

    if (WEXITSTATUS(stat)) { 

     if (cFiles == 0 && cFolders == 0) { 
      Crear(path); 
     } 

     cFolders = 1; 
     TEMP = malloc(sizeof(char)*(strlen(direntp->d_name) + 25)); 

     if (TEMP == NULL) { 
      perror("Malloc Error: "); 
      exit(1); 
     } 

     if (sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0) { 
     perror("Sprintf Error: "); 
     exit(1); 
     } 

     write(STDOUT_FILENO,TEMP,strlen(TEMP)); 
     f.name = malloc(sizeof(char)*(strlen(direntp->d_name)*2 + 3)); 

     if (f.name = NULL) { 
      perror("Malloc Error: "); 
      exit(1); 
     } 
      //This is the one with the problem!!!  
      if (sprintf(f.name, "%s/%s.a", direntp->d_name, direntp->d_name) < 0) { 
      perror("Sprintf Error: "); 
      exit(1); 
     } 

     l = AddToList(l,&f); 
    } 
} 
+0

Meine beste Schätzung ist, dass eine der Zeichenfolgen nicht null terminiert ist. Ich hatte dieses Problem einige Male, als ich zum ersten Mal C. lernte. – forivall

Antwort

1

Es scheint nicht, wie Sie TEMP sind Zuteilung groß genug zu sein, um

TEMP = malloc(sizeof(char)*(strlen(direntp->d_name) + 25)); 

sollte:

TEMP = malloc(sizeof(char)*(strlen(direntp->d_name)*3 + 25 + 1)); 

Sie drucken d_name dreimal, und Sie benötigen auch ein zusätzliches Byte für den Nullabschluss.

Ebenso auf dieser Linie:

f.name = malloc(sizeof(char)*(strlen(direntp->d_name)*2 + 3)); 

sollte

sein
f.name = malloc(sizeof(char)*(strlen(direntp->d_name)*2 + 3 + 1)); 

für den Null-Terminator zu berücksichtigen.

Mit behauptet wie dies sicher machen helfen können Ihre Berechnungen sind rechts:

int TEMP_size = strlen(direntp->d_name)*3 + 25 + 1; 
    TEMP = malloc(sizeof(char)*TEMP_size); 

    if (TEMP == NULL) { 
     perror("Malloc Error: "); 
     exit(1); 
    } 

    if (sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0) { 
     perror("Sprintf Error: "); 
     exit(1); 
    } 
    assert(strlen(TEMP)+1==TEMP_size); 
+0

Entschuldigung, der Code, den ich gepostet habe, war der alte und die TEMP-Zuweisung wurde behoben, aber der Segmentierungsfehler kommt nicht von TEMP, sondern von sprintf (f.name .....). Das finde ich komisch, sogar mit f.name = malloc (sizeof (char) * (strlen (direntp-> d_name) * 2 + 3 + 1)) starte immer noch denselben Fehler. –

0

„% s /% sa“, so dass ich denke, wenn „% s“ der Länge n ist, dann ist die ganze Zeichenfolge würde n * 2 + 1 + 1 + 1 + 1 = 2n + 4 statt 2n + 3 ... Vergessen Sie nicht das abschließende '\ 0' ,,, sondern ob dies einen Segmentierungsfehler verursachen sollte. . ich habe keine Ahnung ...

// Ja, viele Fehler in Bezug auf die Anzahl der Bytes in diesem Stück Code zuzuweisen ...

0

Sie haben nicht enougth Speicher für diese sprintf zuteilen:

sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name 

Sie ordnen sizeof (direntp-> d_name) 25, aber ich sehe 25 char + 3 * sizeof (direntp-> d_name) +1 zusätzliche Zeichen (Ihr \ 0, die das Ende der Zeichenfolge)

Grüße

+0

Danke, aber ich sagte in den anderen Kommentaren, das war nicht der Fehler, obwohl TEMP jetzt die Korrektur hat, dass der seg Fehler von sprintf kommt (f.name .....) –

+0

sprintf (f.name, "% s /% sa ", direntp-> d_name, direntp-> d_name, ich sehe 2 * strlen (direntp-> d_name) + 3 char + 1 extra char (\ 0 für Ende der Zeichenkette). Du hast 2 * strlen zugewiesen (direntp -> d_name) + nur 3 char. Du vermisst das \ 0-Leerzeichen deines Strings. Edit arf hat nicht gesehen, dass du es vorher probiert hast. – grifos

0

Einige Hinweise zusätzlich zu früheren Antworten zeigen:

  1. die meisten modernen Unix-ähnlichen Systemen haben asprintf() und vasprintf() in stan Dard-Bibliothek, die Puffer selbst zuweist. Die Verwendung von ihnen ist einfacher als das Berechnen der benötigten Größe, das Zuweisen und Aufrufen von sprintf(), selbst wenn sie ein bisschen überladen.

  2. Das Füllen des Puffers und dann das Drucken auf stdout mit write() sieht wie eine unnötige Komplikation gegenüber dem einfachen printf() aus. Die Verwendung von stdio für solche Aufgaben ist viel besser, es sei denn, Sie verwenden etwas, das stdio nicht stabil handhaben kann (als nicht blockierende E/A).

  3. Die Aufgabe, die Sie ausführen, passt viel besser in eine Skriptsprache (Perl, Python, Tcl, Ruby, was auch immer), es sei denn, einige externe seltsame Umstände zwingen Sie, C zu verwenden; C soll auf Unix-Art Bereiche näher am Kernel und Low Level erfüllen. Siehe z.B. "The Art of Unix Programming" für die Argumentation.

+0

Es ist ein Projekt von meiner Universität, deshalb muss ich C benutzen, ich kenne asprintf () ist besser, aber ich habe einige Einschränkungen, welche Befehle ich verwenden kann. –