2013-02-28 2 views
1

Вот код для освобождения весь связанный списокКак проверить бесплатно (узел) работает

void free_list(RecordType *list) 
{ 
    RecordType *tempNode;  /* temporary Node to hold on the value of previous node */ 

    while(list != NULL)   /* as long as the listnode doesn't point to null */ 
    { 
     tempNode = list;   /* let tempNode be listNode in order to free the node */ 
     list = list->next;  /* let list be the next list (iteration) */ 
     free(tempNode);   /* free the node! */ 
    } 
} 

Я думаю, что сам по себе этот код работает нормально (?), Но я понятия не имею, как проверить. я только применил теорию (например # из FreeS должен = к # из mallocs)

Так вот некоторые вопросы, которые я задаюсь вопросом ...

  1. ли этот метод работать?
  2. Нужно ли мне malloc tempNode?
  3. Я инициализируется tempNode, прежде чем время цикла ... но после того, как я бесплатно, tempNode до сих пор работает ... Я не реально получить, что часть

Теория, которую я использовал:

  1. # свободные() == # из таНоса()
  2. Вам нужен временный узел для хранения текущего узла
  3. Пусть текущий узел, равного следующего узел
  4. свободных текущего узла, используя Tempor ary node

Если какая-либо из моих теорий звучит неправильно, объясните, пожалуйста!

Спасибо!

+0

Его рабочий, предполагая, что вы сделали, по сути, построить свой список правильно (и это выглядит, как вы, вероятно, сделал). Ваш список теорий спот-на. – WhozCraig

ответ

1

Метод, безусловно, работает - но он должен быть malloc d сначала до free ing. В противном случае это неопределенное поведение.

Вам не нужно malloc()tempNode только если list было ранее malloc() d.

Третья часть - это неопределенное поведение. После free() данные все еще могут существовать, но помечены как перезаписываемые. Вы не можете полагаться на узел, если он free() d

+0

Итак, если я правильно использовал первый способ вставки, чтобы сделать список с помощью malloc, мне нужно malloc tempNode? – LarsChung

+0

@LarsChung нет, вы этого не делаете. Infact, если вы это сделаете, а затем скажите 'tempNode = list; 'тогда youu будет утечка памяти здесь. Когда вы вводите строку 'tempNode = list; 'вы, по сути, указываете' tempNode' на то, что указывает 'list' (что, надеюсь,' malloc() 'd) –

1

Этот метод работает?

Да, если предположить, что список узлов были динамически распределяемой и не были ранее освобождены

Мне нужно таНос tempNode ли?

Вам не нужно выделять какую-либо память внутри free_list, но все элементы списка должны были быть динамически распределены ранее. Можно вызвать только free на память, которая была выделена с помощью malloc (или calloc)

Я инициализируется tempNode до того, пока петли ... но после того, как я свободно, tempNode до сих пор работает ... Я не реально получить, что part

Вызов free возвращает владельца системы памяти в систему. Он может выбрать повторное использование этой памяти немедленно или может оставить ее нетронутой в течение некоторого времени. Нет ничего, что могло бы остановить повторный доступ к памяти, но результаты чтения или записи не определены.

Если вы хотите, чтобы сделать его более трудным для клиентского кода, чтобы случайно доступа освободили памяти, вы можете изменить free_list на NULL их указатель

void free_list(RecordType **list) 
{ 
    RecordType *tempNode; 
    while(*list != NULL) { 
     tempNode = *list; 
     list = tempNode->next; 
     free(tempNode); 
    } 
    *list = NULL; 
} 

Если вы хотите, чтобы убедиться, что вы действительно освободили всю память, смотрите в использование valgrind.Это сообщит о любых утечках памяти, а также отображает некоторые типы недопустимого доступа к памяти.

+0

+1, хотя я думаю, что его вопрос о 'tempNode' был специфичен для характера его цикла. То, что 'tempNode' * указывает *, очевидно, было правильно распределено (или NULL), или это UB, но в контексте' free_list() 'no' malloc() '* calls * необходимо. И только потому, что мне иногда нравится делать мои коллеги [царапать головы] (http://ideone.com/rIyqjD) (обратите внимание на 'free()' call = P) – WhozCraig

+0

Спасибо, я думаю, вы правы, что я неправильно интерпретировал ту часть вопроса. Я обновил этот бит моего ответа. – simonc

0

Лучший способ проверить ваш код - это интерактивное отслеживание с помощью отладчика. Gdb в KDevelop на Linux или отладчик MS Visual Studio на MS Windows являются идеальными. Я буду использовать позже для этой демонстрации.

Этот код определяет однонаправленный список целых чисел с тремя функциями: ListPush() добавляет в список целое число, ListPrint() отображает содержимое списка, а ListDestroy() уничтожает список. В main() я вставляю 3 целых числа в список, печатаю их и уничтожаю список.

#include <malloc.h> 
#include <stdlib.h> 
#include <stdio.h> 
typedef struct Node NODE, *PNODE; 
typedef struct Node { 
    int item; 
    PNODE next; 
}; 
PNODE ListPush(PNODE head, int item) { 
    PNODE p; 
    PNODE n = (PNODE) malloc(sizeof(NODE)); 
    if (!n) exit(1); 
    n->next = 0; 
    n->item = item; 

    if (!head) { 
     head = n; 
    } 
    else { 
     for (p=head; p->next != 0; p=p->next); 
     p->next = n;  
    } 
    return head; 
} 

void ListPrint(PNODE head) { 
    PNODE p; 
    printf("List contents:\n\n"); 
    for (p=head; p!=0; p=p->next) { 
     printf("%d ", p->item); 
    } 
} 

void ListDestroy(PNODE head) { 
    PNODE n, c = head; 
    if (!head) return; 
    do { 
     n = c->next; 
     free(c); 
     c = n; 
    } while (c); 

} 

int main() { 
    int i; 
    int a[3] = {1,2,3}; 
    PNODE head = 0; 
    for (i = 0; i<3; ++i) { 
     head = ListPush(head, a[i]); 
    } 
    ListPrint(head); 
    ListDestroy(head); 
    return 0; 
} 

Три прилагаемых изображения иллюстрируют 2 этапа программы (MSVS2012 Debugger).

Первое показывает состояние соответствующих локальных варов после окончания цикла(). Посмотрите на переменную головы и продолжайте движение по дереву. Вы можете увидеть три узла с их содержимым: целые числа 1,2 и 3 соответственно.

Второе изображение показывает переменные внутри ListDestroy() после первого вызова free(). Вы можете видеть, что голова указывает на освобожденную память (красные круги) и указатель в переменной c указывает на следующий узел, который уничтожается в следующем цикле.

After 3 pushes

After first call to free()

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