我试图写一个双向链表。以下代码通过了我的测试,但我在next
方向和prev
方向为新节点分配内存。具体来说,问题是我认为我不应该在current
函数中分配push
,因为这些节点已经在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);
}
答案 0 :(得分:3)
根据我上面的评论:
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
,但错误处理会让所有事情变得混乱!
答案 1 :(得分:2)
一个明显的错误是您在指针大小位中分配内存,而不是列表节点的大小。尝试将mallocs
更改为:
ptr = malloc(sizeof(struct list)); // note the missing '*'
我敢打赌,这将彻底解决你的大部分记忆问题。但并非所有,例如,在分配电流后,你仍然会通过覆盖电流来进行内存泄漏(尽管如其他海报所说的那样,它并不是必需的)
答案 2 :(得分:1)
我认为你不应该每次推送都分配一个新列表(这里current
);只需指出head
即可。在这里,您只需分配一个列表,然后在指向此列表的指针指向您的head
之后。所以没有必要分配它。
分配创建了程序可写的足够空间,指针只存储地址,这就是你想要的地址,只要你迭代current
而不是你的head
,你的指针就不会改变tail->prev
。
我本可以在这些解释中迷失自己,也许会失去你的问题的目的,但希望这会对你有帮助。
哦,最后一件事,也许你应该head
点{{1}}。
但是我仍然不明白为什么你在你的init中分配2个节点而不是一个接一个地将它们推到你的头上