2011-07-13 8 views
0

Je me suis gratté la tête pendant des heures. Cela lit les données d'un fichier texte dans la structure (chaque ligne a quatre chaînes, et chaque ligne représente un nouvel étudiant). Je reçois un défaut de seg sur le realloc (près de la fin). Je soupçonne que je ne comprends pas comment le pointeur interagit avec malloc/realloc.Utilisation de realloc sur une matrice de structures

struct student* createInitialStudentArray(FILE *fp) { 
    char buf[20+1] = {0}; 
    int word = 1, studcount = 1; 
    struct student* studentArray = malloc(sizeof(struct student)); 
    assert(studentArray != NULL); 
    while (fscanf(fp, " %20s", buf) != EOF) { 
     if (word % 4 == 1) { 
      sscanf(buf, "%4d", &studentArray[studcount].studentID); 
      word++; 
     } 
     else if (word % 4 == 2) { 
      strcpy(studentArray[studcount].lastName, buf); 
      word++; 
     } 
     else if (word % 4 == 3) { 
      strcpy(studentArray[studcount].firstName, buf); 
      word++; 
     } 
     else if (word % 4 == 0) { 
      sscanf(buf, "%10lld", &studentArray[studcount].phoneNumber); 
      word = 1; 
      studcount++; 
      studentArray = realloc(studentArray, studcount * sizeof(struct student)); 
      assert(studentArray != NULL); 
     } 
    } 

    return studentArray; 
} 

Quelle est l'origine de ce défaut de seg?

Merci à l'avance,

Gus

+2

dépit de ne pas être la cause racine de votre segfault, la façon dont vous utilisez realloc peut conduire à des fuites de mémoire lorsque realloc ne peut pas allouer plus de mémoire , car il retournera NULL et vous perdrez le pointeur vers le tampon précédent – Vitor

Répondre

3

Si votre tableau a studcount éléments, puis studentArray[studcount] est passé à la fin du tableau, et l'écriture il n'y a pas permis. Les éléments valides pour accéder sont 0 à studcount-1. Vous devez remplacer studentArray[studcount] par studentArray[studcount-1] partout pour écrire dans le dernier élément. Notez que le faire de cette façon vous donnera une valeur studcount trop grande par 1 lorsque la boucle est terminée, car le dernier élément du tableau est toujours vide ou incomplet. Comme mentionné par pmg dans les commentaires, une autre solution est d'initialiser studcount à 0 qui résoudra les deux problèmes ci-dessus, mais alors vous devez vous assurer d'allouer de la place pour au moins studcount+1 éléments avant d'en écrire un nouveau.

+1

+1 Ou, mieux, initialisez 'studcount' à 0 – pmg

+0

Merci! Cela l'a fait. – 9us

0

Votre boucle et la structure scanf semble mal ..

Tout d'abord vous avez lu une chaîne (la scanf dans la condition while), puis un int (word == 1), puis une autre chaîne (tant que condition à nouveau, word == 2), une autre chaîne (encore une condition, word == 3), et enfin une autre chaîne et un long long int (word == 4).

Je réécris votre boucle intérieure avec un commutateur

/* pseudo-code */ 
while (fgets(buf, sizeof buf, stdin)) { 
    /* realloc here */ 
    chk = sscanf(buf, "%4d%20s%20s%10lld", 
       &studentArray[studcount].studentID, 
       studentArray[studcount].lastName, 
       studentArray[studcount].firstName, 
       &studentArray[studcount].phoneNumber); 
    if (chk != 4) /* deal with error */; 
} 
+0

Merci, cela semble beaucoup plus propre. – 9us

+0

Un problème: sscanf ne se souvient pas des emplacements dans une chaîne, n'est-ce pas? Donc, à chaque fois que j'appelle sscanf, ça commence au début, alors comment est-ce que je pourrais scanner le deuxième mot de la chaîne? – 9us

+0

Hmmm ... oui, vous avez raison. Mieux vaut tout faire une seule fois. Réviser la réponse :) – pmg

Questions connexes