Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 释放链接列表中的节点_C_List_Pointers_Free - Fatal编程技术网

C 释放链接列表中的节点

C 释放链接列表中的节点,c,list,pointers,free,C,List,Pointers,Free,我正在用C语言做一些链表练习,遇到了一个指针问题。我正在尝试实现函数RemoveListByIndex(list,index)。 到目前为止,我已经完成了这个代码 void RemoveNodeByIndex(struct node** head,int index) // NOT WORKING YET { // Remove node list struct node* current = GetNodeByIndex(*(&head), index); struct n

我正在用C语言做一些链表练习,遇到了一个指针问题。我正在尝试实现函数RemoveListByIndex(list,index)。 到目前为止,我已经完成了这个代码

void RemoveNodeByIndex(struct node** head,int index) // NOT WORKING YET
{
  // Remove node list
  struct node* current = GetNodeByIndex(*(&head), index);
  struct node* prev    = GetNodeByIndex(*(&head), index-1);

  // For debugging
  PrintHRLine();
  printf("Deleting item %d from list.\n", index);
  printf("Item %d data = %d\n", index, current->data);
  PrintHRLine();
  // Change link from prev link node to the next
  prev->link = current->link;

  // Unlink node wished to delete
  current->link = NULL;
  current->data = 0;

  // Free data
  free((struct node*) current);
}
GetNodeByIndex函数:

struct node* GetNodeByIndex(struct node** list, int index)
{
  // Return node by an index given
  // if error it returns NULL
  // for i < index
  //       next_node <- node.link
  //     node <- next.node
  // return next_node

  struct node* current = *list;
  int counter = 0;

  if (current)
    {
      while (current->link != NULL)
    {
      if (counter == index)
        return current;

      current = current->link;
      counter++;
    }
    }
  else
    {
      return NULL;
    }

  return NULL;
}
我从主代码中调用函数,如下所示:

struct node
{
  int data;
  struct node* link;
};
int main()
{
  struct node* head = NULL;
  struct node* edit_node = NULL;

  int i;
  edit_node = (struct node*)malloc(sizeof(struct node));

  // Create a list of 10 elements
  for (i = 0; i < SIZE_OF_LIST; i++)
    {
      struct node* item = (struct node*) malloc(sizeof(struct node));
      item->data = i;
      if (i==0)
        head = item;
      printf("(item+%d)->data = %d\n",i,i);
      if (i<SIZE_OF_LIST-1)
    {
      item->link = (item+i+1);
      printf("(item+%d->link = (item+%d+1);\n", i, i);
      printf("(item+%d adress = 0x%lx\n",i, (unsigned long int) &item+i);
    }
      else 
    {
      item->link = NULL;
      printf("(item+%d->link = NULL;\n", i);
    }
}

  // RemoveNodeByIndex(head, 5);
  // PrintListData(&head);
  edit_node->data = 1001;
  AddLastNode(&head, &edit_node);
  SearchNode(&head, 101);
  RemoveNodeByIndex(&head, 8);
  PrintListData(&head);

  // Free memory
  free(item);
  free(edit_node);
  free(head);

  return 0;
}
我怀疑我在处理指针时出了什么差错。 但我做错了什么

编辑: 我已将所有源代码包含在以下链接中: 我在这里包括了程序生成的所有输出:


谢谢,请提前通知。

您没有发布完整的代码,但我认为问题出在
free()

free()
的手册页所示

free()释放ptr指向的内存空间,该内存空间必须由以前对malloc()、calloc()或realloc()的调用返回。其他- wise,或者如果之前已经调用了free(ptr),则会发生未定义的行为。如果ptr为NULL,则不执行任何操作

我认为在您的cse中,
current
的指针不是由
malloc()
calloc()
分配的。通过执行
(*(头部)+索引)您指向的是其他地方


编辑:

在代码中,不要使用
item=(struct node*)malloc(sizeof(struct node)*10)
,尝试分别分配每个
节点。此外,在删除
n
th节点时,方法应该是转到
n-1
th节点,获取
next
[或
link
]指针并
free()


编辑2:

为什么

  struct node* current = GetNodeByIndex(*(&head), index);
  struct node* prev    = GetNodeByIndex(*(&head), index);

current
prev
是否相同?您认为如何?

您正在尝试删除最后一个节点

结构节点*当前=((头部)+索引);这指向索引+1节点,而不是索引节点 结构节点prev=(*(头部)+索引-1);这指向的是索引节点,而不是索引-1

伙计,您正试图删除malloc分配的内存的一部分。我认为这是不允许的

尝试单独malloc每个节点,而不是将10个节点聚合为一个malloc,

在“RemoveNodeByIndex”函数中,请检查以下行

struct node* current = GetNodeByIndex(*(&head), index);
struct node* prev    = GetNodeByIndex(*(&head), index);

两者都将具有相同的节点,并且您将当前节点设置为NULL,并且如果删除当前节点,则不会维护任何链接。这可能会导致未定义的行为。

您的代码尝试实现一个链接列表,其中节点存储在单独的节点池中,
。您对此实现有一些误解:

  • 如果池大小是固定的,则应该只有一个分配,即池的10个节点的分配。所有其他指针——列表头、当前迭代器节点、节点中的链接和临时工作节点——都应该是指向现有内存的指针

  • 因为只有一个分配,所以最后应该只有一个
    免费
    ,即
    免费(项目)
    。传递到
    free
    的指针必须与从
    malloc
    返回的指针相同。您的h列表头可能会随着工作指针的变化而变化;你显然不能释放这些

  • 当您谈论索引时,您在这里谈论两个不同的概念:项索引,它是数组
    items
    中节点的索引;列表索引,它是列表中的索引,列表头位于索引
    0

  • 由于
    items
    是一个节点数组,因此可以使用
    items+item_ix
    在项目索引处获取节点。这不适用于链接列表。链表的优点是插入和删除速度快。(好吧,这确实适用于双链接列表。)缺点是按索引查找节点的速度慢:您必须从头部开始计数并在列表中迭代

  • 将列表头作为指向头节点的指针传递给函数。只有当函数更改列表时(例如,当它删除或添加节点时),才需要这样做。当您只是检查列表时,即在查找节点或打印节点时,不需要这样做;指向节点的指针在这里就足够了

  • 添加或删除节点时,
    项的分配内存保持不变。例如,如果列表为空,
    items
    会保存10个节点(其数据是任意的)。您需要一种机制来判断列表中是否正在使用节点。这可能是
    struct node
    中的附加条目,也可能是辅助数组

  • 您可以在
    main
    中的循环中创建列表。更好的实现是使用一个额外的函数,将节点添加到列表中。当然,这样的函数必须了解节点池,因为它需要从池中获取节点

  • 此时,您应该将整个列表逻辑封装在一个结构中。将指针传递给列表结构并在其中进行所有更改,而不是头指针

我在下面展示了一个示例实现,它不在堆上使用分配,而是在堆栈上使用固定大小的池。代码使用hree数据结构:

  • 节点与代码中的相同

  • 池是一个固定大小的节点池,可以在堆栈上创建,并且应该初始化为零,以便正常工作。池使用一个额外的数组(
    used
    )跟踪可用节点。固定池大小由编译时常量定义

  • 列表包含对列表头节点的引用和对池的引用。(多个列表可能共享一个池,但这些列表的最大节点总数是固定的。)它还跟踪大小,这不是必需的,但很容易做到

main
中的客户端代码仅在初始化结构后通过函数访问这些结构。注意游泳池是怎样的
struct node* current = GetNodeByIndex(*(&head), index);
struct node* prev    = GetNodeByIndex(*(&head), index);
#include <stdio.h>
#include <stdlib.h>

#define POOL_SIZE 10

struct node {                       /* List node */
    int data;
    struct node *next;
};

struct pool {                       /* Fixed-size node pool */
    char used[POOL_SIZE];           /* used/free markers */
    struct node data[POOL_SIZE];    /* associated nodes */
};

struct list {                       /* List structure */
    struct pool *pool;              /* Node pool reference */
    struct node *head;
    struct node *tail;
    int size;
};



/*
 *      Find an unused node and return it. If there are no unused
 *      nodes in the pool, return NULL:
 */
struct node *pool_new_node(struct pool *pool)
{
    int i;

    for (i = 0; i < POOL_SIZE; i++) {
        if (pool->used[i] == 0) {
            pool->used[i] = 1;
            return pool->data + i;
        }
    }

    return NULL;
}

/*
 *      Mark a node in the pool as unused, effectively freeing it.
 *      Return 0 on success, -1 on error.
 */
int pool_free_node(struct pool *pool, struct node *node)
{
    int i = node - pool->data;

    if (i < 0 || i >= POOL_SIZE) return -1;
    if (pool->used[i] == 0) return -1;

    pool->used[i] = 0;
    return 0;
}

/*
 *      Append an item with value x at the tail.
 */
struct node *list_append(struct list *list, int x)
{
    struct node *node = pool_new_node(list->pool);

    if (node == NULL) return NULL;

    node->next = NULL;
    node->data = x;

    if (list->tail) {
        list->tail->next = node;
    } else {
        list->head = node;
    }
    list->tail = node;    
    list->size++;

    return node;
}

/*
 *      Return ix'th node in list or NULL.
 */
struct node *list_find_by_index(const struct list *list, int ix)
{
    struct node *node = list->head;

    if (ix < 0 || ix >= list->size) return NULL;

    while (node) {
        if (ix-- == 0) return node;
        node = node->next;
    }

    return NULL;    
}

/*
 *      Return first node with given data or NULL.
 */
struct node *list_find_by_data(const struct list *list, int data)
{
    struct node *node = list->head;

    while (node) {
        if (node->data == data) return node;
        node = node->next;
    }

    return NULL;
}

/*
 *      Delete given node from list.
 */
void list_delete_node(struct list *list, struct node *node)
{
    if (node) {
        struct node **iter = &list->head;

        while (*iter) {
            if (*iter == node) {
                *iter = node->next;
                pool_free_node(list->pool, node);
                list->size--;
                return;
            }
            iter = &(*iter)->next;
        }
    }
}

/*
 *      Delete node at index from list.
 */
void list_delete_by_index(struct list *list, int ix)
{
    struct node *node = list_find_by_index(list, ix);

    if (node) list_delete_node(list, node);
}


/*
 *      Print the list items
 */
void list_print(const struct list *list)
{
    struct node *node = list->head;

    printf("%d items: [", list->size);
    while (node) {
        if (node != list->head) printf(", ");
        printf("%d", node->data);
        node = node->next;
    }
    printf("]\n");
}



/*
 *      Example client code
 */
int main()
{
    struct pool pool = {{0}};
    struct list list = {&pool};
    struct node *node;

    int i;

    for (i = 0; i < 12; i++) {
        list_append(&list, i);
        list_print(&list);
    }

    node = list_find_by_index(&list, 9);
    if (node) node->data = 1001;

    node = list_find_by_index(&list, 10);
    if (node) node->data = 1001;

    list_print(&list);

    node = list_find_by_data(&list, 7);
    if (node) node->data = 999;

    list_print(&list);

    list_delete_by_index(&list, 0);
    list_delete_by_index(&list, 0);
    list_delete_by_index(&list, 0);    
    list_delete_by_index(&list, 5);

    list_print(&list);

    for (i = -10; i < 0; i++) {
        list_append(&list, i);
        list_print(&list);
    }

    list_print(&list);

    return 0;
}