2013-06-10 4 views
0

Ceci est apparu dans un projet de classe. La question peut être un peu trop longue, mais comme je ne sais pas exactement où le problème pourrait être, il serait peut-être utile de le faire en entier.malloc, calloc, et les tableaux dynamiques

Disons que nous avons une structure de la forme:

typedef struct 
{ 
    char *name; 
    char **friends; 
    int numFriends; 
} User; 

et nous avons des conteneurs pour la structure:

typedef struct 
{ 
    User *users; 
    int db_size; 
} DB; 

Nous avons également deux fonctions de gestion amis:

void makeFriends(char *name1, char *name2, DB *db) 
{ 
    User user1 = findByName(name1); 
    User user2 = findByName(name2); 

    user1.friends[numFriends] = name2; 
    user2.friends[numFriends] = name1; 

    user1.numFriends++; 
    user2.numFriends++; 

    update_db(user1, db); 
    update_db(user2, db); 
} 

void unmakeFriends(char *name1, char *name2, DB *db) 
{ 
    User user1 = getByName(name1); 
    User user2 = getByName(name2); 

    for (int i = 0; i < user1.numFriends; ++i) 
    { 
     if (strcmp(user1.friends[i]), name2) 
     { 
      int size = 0; 
      char *newFriendList = malloc(APPROPRIATE_AMOUNT); 


      for (int j = 0; j < count; ++i) 
      { 
       if (j != i) 
       { 
        newFriendList[size] = user1.friends[j]; 
        size++; 
       } 
      } 

      user1.friends = newFriendList; 
      user1.numFriends = size; 

      // this breaks things for some reason 
      //free(newFriendList); 
     } 
    } 

    // and the same for user2 

    for (int i = 0; i < user2.numFriends; ++i) 
    { 
     if (strcmp(user2.friends[i]), name2) 
     { 
      int size = 0; 

      // this can lead to the corruption of user1's list 
      // char *newFriendList = malloc(APPROPRIATE_AMOUNT); 
      // but this works fine 
      char *newFriendList = calloc(someNum, APPROPRIATE_AMOUNT); 


      for (int j = 0; j < count; ++i) 
      { 
       if (j != i) 
       { 
        newFriendList[size] = user2.friends[j]; 
        size++; 
       } 
      } 

      user2.friends = newFriendList; 
      user2.numFriends = size; 

      // this breaks things for some reason 
      //free(newFriendList); 
     } 
    } 

    update_db(user1, db); 
    update_db(user2, db); 
} 

Nous créons trois utilisateurs en leur donnant un nom et en leur allouant de la mémoire pour leur liste d'amis:

User vladimir = { .name = "Vladimir", .friends = malloc(APPROPRIATE_AMOUNT), 0 }; 
User estragon = { .name = "Estragon", .friends = malloc(APPROPRIATE_AMOUNT), 0 }; 
User pozzo = { .name = "Pozzo", .friends = malloc(APPROPRIATE_AMOUNT), 0}; 

Maintenant, disons que Vladimir et Estragon veulent devenir des amis, puis Estragon et aussi Pozzo deviennent des amis. Un certain temps s'écoule, et Vladimir et Estragon décident qu'ils ne s'aiment pas vraiment, alors l'un d'eux ne sympathise pas avec l'autre.

Si je lance la fonction unmakeFriends et utiliser malloc deux fois, la première liste de l'utilisateur d'amis est corrompu (comme les noms apparaissant deux fois ou tout autre comportement non défini) au cours de la deuxième boucle . Si j'utilise calloc deux fois, j'obtiens des erreurs de bus ou de bus. Si j'essaie de libérer la mémoire, j'obtiens des erreurs de bus. Si j'utilise le code tel qu'il est actuellement, un comme malloc, l'autre comme calloc, cela fonctionne comme prévu.

Que se passe-t-il et pourquoi?

+0

Vous devez créer une liste d'amis liée, de sorte que vous puissiez en extraire une au milieu de la liste. Chaque entrée de la liste a sa propre mémoire allouée/libérée, et les autres entrées sont laissées seules. Google "tutoriel liste c lié". – Floris

Répondre

0

calloc 0 initialise le tampon que vous allouez dynamiquement. malloc le laisse juste comme indésirable.