2012-03-25 15 views
0

Je crée un makefile creator, mais je suis coincé dans cette erreur sur sprintf, le plus curieux, c'est que j'ai plusieurs sprintf avant celui avec l'erreur et ils fonctionnent bien.Segmentation Fault avec sprintf

Voici le 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

Ma meilleure estimation est que l'une des chaînes n'est pas terminée par un caractère nul. J'ai eu ce problème quelques fois quand j'ai commencé à apprendre C. – forivall

Répondre

1

Il ne semble pas que vous allouez TEMP être assez grand

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

devrait être:

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

Vous imprimez d_name trois fois, et vous avez également besoin d'un octet supplémentaire pour le terminateur null.

De même, sur cette ligne:

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

devrait être

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

pour tenir compte de la terminaison nulle.

L'utilisation affirme comme cela peut aider à vous assurer que vos calculs sont justes:

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

Désolé le code que j'ai posté était l'ancien et l'allocation de TEMP a été fixée, mais la faute de segmentation ne vient pas de TEMP, mais de sprintf (f.name .....). C'est ce que j'ai trouvé bizarre, même avec f.name = malloc (sizeof (char) * (strlen (direntp-> d_name) * 2 + 3 + 1)) lance toujours la même erreur. –

0

« % s /% sa », donc je pense que si « % s » est de longueur n, la chaîne entière serait prendre n * 2 + 1 + 1 + 1 + 1 = 2n + 4 plutôt que 2n + 3 ... ne pas oublier la terminaison '\ 0' ,,, mais quant à savoir si cela devrait provoquer un défaut de segmentation. . Je ne sais pas ...

// Oui, beaucoup d'erreurs concernant le nombre d'octets à allouer dans ce morceau de code ...

0

Vous ne l'avez pas allouer de la mémoire de cette sprintf peuvent acceuillir:

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

vous allouez sizeof (direntp-> d_name) +25, mais je vois 25 ombles + 3 * sizeof (direntp-> d_name) +1 ombles supplémentaire (votre \ 0 qui indiquent la fin de votre chaîne)

concernant

+0

Merci, mais comme je l'ai dit dans les autres commentaires, ce n'était pas l'erreur, même si TEMP a maintenant la correction de la faute seg vient de sprintf (f.name .....) –

+0

sprintf (f.name, "% s /% sa ", direntp-> d_name, direntp-> d_name, je vois 2 * strlen (direntp-> d_name) + 3 char + 1 char supplémentaire (\ 0 pour la fin de la chaine) Vous avez alloué 2 * strlen (direntp -> d_name) + 3 caractères seulement Vous manquez l'espace \ 0 de votre chaîne Modifier arf ne vous voyait pas déjà essayé – grifos

0

Quelques notes en plus des réponses précédentes:

  1. la plupart des systèmes Unix modernes ont asprintf() et vasprintf() dans stan dard bibliothèque qui alloue le tampon par eux-mêmes. Les utiliser est plus simple que de calculer la taille nécessaire, allouer et appeler sprintf(), même si elles sont surexposées un peu.

  2. Le remplissage du tampon, puis l'impression sur stdout à l'aide de write() ressemble à une complication inutile par rapport à printf(). Utiliser stdio pour de telles tâches est bien meilleur si vous n'utilisez pas quelque chose que stdio ne peut pas gérer de façon stable (comme des E/S non bloquantes). La tâche que vous effectuez est beaucoup mieux adaptée dans un langage de script (Perl, Python, Tcl, Ruby, peu importe), à ​​moins que des circonstances étranges externes ne vous obligent à utiliser C; C est supposé en Unix pour remplir les zones les plus proches du noyau et du bas niveau. Voir par exemple "The Art of Unix Programming" pour le raisonnement.

+0

C'est un projet de mon université, c'est pourquoi je dois utiliser C, je sais asprintf () est meilleur mais j'ai quelques restrictions quant aux commandes que je peux utiliser. –