Уничтожить дек с помощью указателей и освободить в C

Я пытаюсь уничтожить свою двухстороннюю очередь, но почему-то не справляюсь с указателями. Я написал следующий код (двухсторонняя очередь - указатель на указатель, который указывает на первый элемент двухсторонней очереди). DequeItem - это структуры с полями next (указатель на следующий элемент) и данными (void *).

void deque_destroy(DequeItem **deque) {
    DequeItem *temp;
    DequeItem *item;
    for (item = *deque; item != NULL; item = temp) {
        printf("%d", *((int*)((item)->data)));
        temp = item->next;
        free(item);
    }
}

Объявление структуры:

struct DequeItem {
  void *data;                  // Data stored in the deque item

  struct DequeItem *previous;  // Pointer to the previous DequeItem in the ring
  struct DequeItem *next;      // Pointer to the next DequeItem in the ring
};

typedef struct DequeItem DequeItem;

person rize    schedule 25.04.2012    source источник
comment
Так что именно не работает?   -  person Ed S.    schedule 25.04.2012
comment
Я получаю ошибку сегментации. В gdb: не удалось получить доступ к памяти. Причина: программа получила сигнал EXC_BAD_ACCESS, не удалось получить доступ к памяти. Причина: 13 по адресу: 0x0000000000000000. Итак, у меня есть нулевой указатель, верно?   -  person rize    schedule 25.04.2012
comment
Ошибка сегментации происходит в первой строке цикла for, поэтому printf ().   -  person rize    schedule 25.04.2012
comment
элемент не равен NULL, но данные могут быть, и, поскольку вы разыменовываете его, вы получите BAD_ACCESS   -  person msam    schedule 25.04.2012


Ответы (2)


Выглядит правильно, хорошо зачитано temp перед тем, как вы позвоните free() по этому вопросу, это распространенная ошибка новичков, которой вы избежали.

Я думаю, вам нужно предоставить больше информации о том, что идет не так, и, возможно, также объявления структур.

Член data также динамически выделяет память? Если это так, вам может потребоваться вызов free(item->data);, в зависимости от того, как он был выделен при создании элемента.

Как отмечали комментаторы, ваш data указатель может быть NULL, поэтому вам следует проверить его перед печатью:

if(item->data != NULL)
  printf("%d\n", *(int *) item->data);

Примечание:

  • Упрощение выражения приведения упрощает чтение.
  • Включите перевод строки ('\n') в строку printf(), чтобы избежать путаницы с буферизацией и визуального разделения значений.
person unwind    schedule 25.04.2012

Проблема заключалась в том, что следующий указатель последнего элемента (задний элемент) в двухсторонней очереди будет указывать на первый элемент (передний элемент), даже если первый элемент был уничтожен. Я исправил это, установив

(*deque)->previous->next = NULL

перед циклом for выше. Спасибо за помощь!

person rize    schedule 25.04.2012
comment
то есть следующий указатель последнего элемента был чем-то иным, чем NULL, когда цикл достигает последнего элемента и эффективно пытается освободить память по адресу, который ранее содержал передний элемент. - person rize; 25.04.2012