2016-01-05 3 views
0

Я получил структуру, которая определяется следующим образом:Как освободить двойной указатель struct в C?

typedef struct { 
char userType;       // - The type of the user. 
char userName[userName_len];   // - The user's user name. 
char password[password_len];   // - The user's password. 
char id[id_len];      // - The user's id. 
char firstName[userName_len];   // - The users first name. 
char lastName[userName_len];   // - The user's surname. 
char address[address_len];    // - The user's address. 
}Users; 

и указатель для этой структуры в главной функции (не глобальный указатель):

Users* users_db = NULL; 

заполняет, что база данных из текстового файла и посылая указатель на него, как это:

Fill_Databases(&users_db,&qnty); //qnty is a pointer to Quantity struct used for help. 

Fill_Databases передает указатель на другую функцию, как это:

Fill_Users_db(users_db, &*qnty); 

В этой функции имеется выделение памяти с использованием calloc.

Теперь мне нужно освободить stucts, и я получаю проблему с рабочим временем «вызвал точку останова».

Я посылаю его Free_Databases функционировать точно так же, как я выделить память для эм и пытается освободить им, как это:

void Free_Users_db(Users** users_db, Quantity qnty) 
{ 
    int i; 
    for (i = 0; i < qnty.Users; i++) 
    { 
     free(users_db[i]); 
     users_db[i] = NULL; 
    } 
    free(users_db); 
    users_db = NULL; 
    puts("users db free"); 
} 

Что случилось с этим? И какой правильный способ освободить их?

редактирование: Выделение добавлено:

void Fill_Users_db(Users** users_db, Quantity* qnty) 
{ 
    //fills the employee database array according to the file 
    int num_of_users = 0, i; 
    FILE *file = fopen("Users.txt", "r"); //open the file 
    if (!file) //if failed to open file 
    { 
     printf("Error opening file!\n"); 
     return; 
    } 
    fscanf(file, "%d", &qnty->Users); 
    *users_db = (Users*)calloc(qnty->Users, sizeof(Users)); //allocate memory and nullify elements //used calloc coz it takes 2 arguments and not 1 as calloc. 
    if (!*users_db) 
    { 
     printf("Memory allocation failed!\n"); 
     return; 
    } 
    //for each user get data from the file and allocate memory to the relevant struct variables 
    for (i = 0; !feof(file); i++) 
    { 
     fscanf(file, "%s" "%s" "%s" "%s" "%s" "%s", &(*users_db)[i].userType, &(*users_db)[i].userName, &(*users_db)[i].password, &(*users_db)[i].id, &(*users_db)[i].firstName, &(*users_db)[i].lastName); 
     fgetline(&(*users_db)[i].address, file); 
    } 

    fclose(file); //close the file 
} 
+0

Можете ли вы добавить дополнительный код о том, как вы выделяете память для users_db? – Jay

+0

@Jay добавил (а): –

+1

Обратите внимание: 'feof' на самом деле неверен как циферблат, так как вам нужно прочитать прошлое' EOF'. – Jason

ответ

2

users_db определяется в главной функции как массив Users структур, а не массив указателей. Следовательно, это ошибка для free() отдельных элементов массива. Кроме того, вам нужно разыменовать указатель users_db, поскольку вы передаете его как двойной указатель. Попробуйте следующее.

void Free_Users_db(Users** users_db, Quantity qnty) 
{ 
    free(*users_db); 
    *users_db = NULL; 
    puts("users db free"); 
} 
+0

Я уже пробовал это как это, и это работает, но как насчет других элементов массива Users, не должен ли я освобождать их? Это освобождает только указатель? Я понимаю, что я должен освободить все элементы массива? –

+1

Все элементы массива выделяются сразу, с одним вызовом 'calloc()'. Обратите внимание, что размер блока - это количество элементов массива, умноженное на размер каждого элемента. Это всего лишь один блок памяти, поэтому он должен быть сразу освобожден. Вы не можете передавать произвольные указатели на 'free()', вы должны передать указатель, который был возвращен из одного из семейств функций 'malloc(). –

+1

Если вы использовали 'users_db' в качестве массива указателей, вы могли бы затем вызвать' calloc() 'один раз для каждого элемента массива. В этой ситуации вам нужно будет вызвать 'free()' один раз для каждого элемента, когда вы закончите. Но в вашем коде все делается с помощью одного вызова 'calloc()', поэтому вы просто вызываете 'free()' один раз. Вам необходимо сопоставить каждый вызов функции распределения памяти с соответствующим вызовом 'free()'. –

1
void Free_Users_db(Users** users_db, Quantity qnty) 
{ 
    int i; 
    for (i = 0; i < qnty.Users; i++) 
    { 
     free(users_db[i]); 
     users_db[i] = NULL; 
    } 
    free(users_db); 
    users_db = NULL; 
    puts("users db free"); 
} 

должен быть

void Free_Users_db(Users** users_db, Quantity qnty) 
    { 
     int i; 
     /* for (i = 0; i < qnty.Users; i++) 
     { 
      free(users_db[i]); 
      users_db[i] = NULL; 
     }*/ 
     free(*users_db); 
     *users_db = NULL; 
     puts("users db free"); 
    } 

Как вы можете видеть в функции Fill_Users_db, есть только один вызов calloc. Почему вы сопоставляете один вызов функции распределения с несколькими вызовами на free? Это неверно. Каждый вызов функции распределения, такой как malloc или calloc, должен быть сопоставлен только одному вызову free.

+1

Спасибо вам за объяснение :) Получил это сейчас! –