2011-05-23 1 views
2

Ci-dessous est une fonction d'un programme:Chaînes concaténées sur une autre sans assignation, pourquoi est-ce?

//read the specified file and check for the input ssn 
int readfile(FILE *fptr, PERSON **rptr){ 
    int v=0, i, j; 
    char n2[MAXS+1], b[1]=" "; 

    for(i=0; i<MAXR; i++){ 
     j=i; 
     if(fscanf(fptr, "%c\n%d\n%19s %19s\n%d\n%19s\n%d\n%19s\n%19s\n%d\n%d\n%19s\n\n", 
        &rptr[j]->gender, &rptr[j]->ssn, rptr[j]->name, n2, &rptr[j]->age, 
        rptr[j]->job, &rptr[j]->income, rptr[j]->major, rptr[j]->minor, 
        &rptr[j]->height, &rptr[j]->weight, rptr[j]->religion)==EOF) { 
      i=MAXR; 
     } 
     strcat(rptr[j]->name, b); 
     //strcat(rptr[j]->name, n2); 
     if(&rptr[MAXR]->ssn==&rptr[j]->ssn) 
      v=j; 
    } 
    return v; 
} 

la ligne est commenté comme ça parce que pour une raison quelconque le tableau « b » contient la chaîne « n2 » en dépit d'une évidente absence d'une cession. Cela se produit avant le premier appel Strcat, mais après/pendant l'appel fscanf.

atteint le but souhaité, mais pourquoi n2 est-il concaténé sur la fin de b, en particulier lorsque b ne dispose que d'un espace réservé pour 1 élément de tableau?

Voici un extrait de définitions de variables après l'appel fscanf:

*rptr[j]->name = "Rob" 

b = " Low" 

n2= "Low" 
+0

b n'est pas terminé avec un caractère nul ... il n'a de place que pour un caractère ... un espace ... il y a probablement du contenu parce que vous avez débordé un tampon. – forsvarir

Répondre

3

Cela fonctionne, parce que vous avez eu de la chance. b et n2 se sont trouvés l'un à côté de l'autre dans la mémoire, dans le bon ordre. C ne fait pas de vérification des limites sur les tableaux et vous permettra heureusement de les déborder. Ainsi, vous pouvez déclarer un tableau comme celui-ci:

char someArray[1] = "lots and lots of characters"; 

Le compilateur C (ones certainement vieux) va penser que cela est bien, même si il n'y a clairement pas assez d'espace dans le someArray pour stocker que beaucoup de caractères. Je ne suis pas sûr si c'est défini ce qu'il fera dans cette situation (je ne le soupçonne pas), mais sur mon compilateur il limite la population à la taille du tableau, ainsi il ne déborde pas la limite (someArray=={'l'}).

Votre situation est la même (bien que moins extrême). char b[1] crée un tableau avec suffisamment de place pour stocker 1 octet. Vous mettez un espace dans cet octet, donc il n'y a pas de place pour le terminateur null. strcat, continue à copier la mémoire jusqu'à ce qu'il atteigne un terminateur nul, par conséquent il continuera jusqu'à ce qu'il en trouve un, même si ce n'est pas jusqu'à la fin de la chaîne suivante (ce qui se passe dans votre cas).

Si vous aviez utilisé un compilateur C++, il aurait lancé au moins un avertissement (ou plus probablement une erreur) pour vous dire que vous essayiez de mettre trop d'éléments dans le tableau.

+0

+1, même si je ne l'appellerais pas "chanceux", car il ne fait pas exploser et vous fait savoir qu'il y a un problème * évident *. Le comportement est indéfini selon 6.7.8/2: "Aucun initialiseur ne doit tenter de fournir une valeur pour un objet non contenu dans l'entité en cours d'initialisation" –

+0

@John Bode: Oui, j'avais 50:50 sur moi-même chanceux ... Merci pour la référence :) – forsvarir

2

B doit être de taille 2, 1 pour l'espace, 1 pour le vide.

+0

En d'autres termes, 'b [1] =" ";' est équivalent à 'b [1] = {'', '\ 0'};' – Lundin

+0

@Lundin: Non, 'b [1] =" "; 'est équivalent à' b [1] = {''}; '. 'b [2] =" ";' est équivalent à 'b [2] = {'', 0};' ... – forsvarir

+0

@forsvarir Assez juste, je voulais simplement illustrer pourquoi c'est un bug. – Lundin

Questions connexes