【问题标题】:memory trouble with doubly linked list in CC中双向链表的内存问题
【发布时间】:2014-09-17 15:30:25
【问题描述】:

我正在尝试编写一个双向链表。以下代码通过了我的测试,但我正在为next 方向和prev 方向的新节点分配内存。具体来说,问题是我相信我不应该在push 函数中分配current,因为这些节点已经在过去的迭代中使用new 分配。但是,如果我设置 new->prev = current 而不分配 current 我会遇到分段错误。请注意,如果我不分配current 或使用->prev,下面的代码可以作为单链表正常运行。

删除 malloc for current 后,代码在打印测试后出现段错误(第一次使用 prev)。

#include <stdlib.h>
#include <stdio.h>

struct list{
    int value;
    struct list *next;
    struct list *prev;
};
struct list *head;
struct list *tail;

void init(int val){
    head = (struct list *)malloc(sizeof(struct list *));
    head->value = val;
    head->next = NULL;
    head->prev = NULL;

    tail = malloc(sizeof(struct list *)); 
    tail->value = val;
    tail->next = NULL;
    tail->prev = NULL;

}

void push(int val){
     struct list *new;
     struct list *current;
     new = (struct list *)malloc(sizeof(struct list *)); //allocate memory space for next side
     current = (struct list *)malloc(sizeof(struct list *)); //allocate memory space for prev side
     new->value = val;
     new->next = NULL;
     current = head;
     while(current->next!=NULL){current = current->next;}
     new->prev = current;
     current->next = new;
     tail = new;
 }

 int main(){
     printf("init with 10\n");
     init(10);
     printf("pushing 11\n");
     push(11);
     printf("pushing 12\n");
     push(12);
     printf("pushing 13\n");
     push(13);
     printf("testing\n");
     printf("2-1 %d\n",head->next->prev->value);
     printf("3-1 %d\n",head->next->next->prev->value);
     printf("h4-1 %d\n",head->next->next->next->prev->value);
     printf("t-1 %d\n",tail->prev->value);
     printf("t-2 %d\n",tail->prev->prev->value);
     printf("t %d\n",tail->value);
 }

【问题讨论】:

  • 为什么init()不初始化tail-&gt;prev = NULL;? IMO、tailhead 应该在这里获得相同的值。无需致电malloc() 2 次。留给其他人回答。
  • 只想push一个节点,为什么还要给两个节点分配空间?
  • 如果你不分配电流(你不应该这样做),那么段错误在哪里?
  • init应该声明val的类型,并且只分配头节点,并设置tail = headpush 不应该为current 分配节点,也不需要遍历链表找到结尾,因为tail 指向结尾。

标签: c doubly-linked-list


【解决方案1】:

根据我上面的评论:

void init(int val){
    head = malloc(sizeof *head);
    head->value = val;
    head->next = NULL;
    head->prev = NULL;
    tail = head;
}

void push(int val){
     struct list *new;
     new = malloc(sizeof *new); //allocate memory space for next side
     new->value = val;
     new->next = NULL;
     new->prev = tail;
     tail->next = new;
     tail = new;
 }

您还应该确保malloc 不返回NULL,但错误处理会搞砸一切!

【讨论】:

    【解决方案2】:

    一个明显的错误是您分配的内存是指针大小的位,而不是列表节点的大小。尝试将您的 mallocs 更改为:

    ptr = malloc(sizeof(struct list));  // note the missing '*'
    

    我敢打赌,这将一举解决您的大部分记忆问题。并非全部,例如,在分配电流后,您仍然会通过覆盖当前内存泄漏(尽管正如其他海报所说,这不是必需的)

    【讨论】:

    • 谢谢!这就是问题所在。
    【解决方案3】:

    我认为你不应该每次推送都分配一个新列表(这里是current);只需指出head。在这里,您只是分配一个列表,然后将指向该列表的指针指向您的head。所以没有必要分配它。

    分配会为您的程序创建足够的可写空间,指针仅存储地址,这就是您想要的,因为只要您迭代 current 而不是 head,地址上的指针就不会改变。

    我可能会迷失在这些解释中,也可能会失去你问题的目的,但希望这会对你有所帮助。

    哦,最后一件事,也许你应该让tail-&gt;prev 指向head

    但是我仍然不明白为什么你在你的初始化中分配 2 个节点而不是一个一个地把它们推到你的头上

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      相关资源
      最近更新 更多