2013-06-10 5 views
0

Это появилось в проекте для класса. Вопрос может быть слишком длинным, но, поскольку я не знаю, где именно проблема, возможно, было бы полезно извлечь его в полном объеме.malloc, calloc и динамические массивы

Допустим, мы имеем структуру вида:

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

И у нас есть некоторый контейнер для структуры:

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

У нас также есть две функции для управления друзьями:

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); 
} 

Мы создаем трех пользователей, указывая им имя и выделяя некоторую память для их списка друзей:

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}; 

Теперь, скажем, Владимир и Эстрагон хотят стать друзьями, а затем Эстрагон и Поццо также становятся друзьями. Проходит время, и Владимир и Эстрагон решают, что они не очень любят друг друга, поэтому один из них недружелюбив другого.

Если я запускаю функцию unmakeFriends и использовать malloc дважды список первого пользователя друзей повреждается (например, имена появляются дважды или другим непредсказуемым поведением) во время второго цикла. Если я использую calloc дважды, я получаю это или ошибки шины. Если я попытаюсь освободить память, я получаю ошибки шины. Если я использую код так, как сейчас, один как malloc, другой как calloc, он работает по назначению.

Что происходит и почему?

+0

Вам необходимо создать связанный список друзей, чтобы вы могли взять один из середины списка. Каждая запись в списке имеет выделенную/освобожденную память, а остальные записи остаются в силе. Google "связанный список c учебник". – Floris

ответ

0

calloc 0 инициализирует буфер, который вы динамически выделяете. malloc просто оставляет его как мусор.

Смежные вопросы