在C.设计一个队列在向队列添加元素时出现Segfault
我遇到了一个我正在用C写入的队列程序的问题。这是一个循环队列,所以最后一个项目也必须指向第一个项目。问题存在于addQueue函数中。首先,我检查头指针是否设置为NULL,如果是,则将第一项添加到队列中。但是,head不等于NULL,然后我将该项添加到队列的末尾。我创建了一个迭代指针来进行迭代,直到它找到结尾时为止: iterate-> next == * head; 我遇到的问题是,当我创建迭代并将其设置为* head时,它不会像它应该那样操作。这里是我的代码和我收到的输出,我在代码中添加了一些打印以显示我遇到的问题。在C.设计一个队列在向队列添加元素时出现Segfault
#include <stdlib.h>
#include <stdio.h>
//define the Q element struct
typedef struct _item{
struct _item* next;
struct _item* prev;
int data;
} item;
item * newItem(){
item * node = malloc(sizeof(item));
return node;
}
void initQueue(item ** head){
*head = NULL; //Empty queue means head points to NULL
}
void addQueue(item ** head, item item_p){
//create new item
item * newIt = newItem();
newIt = &item_p;
printf("NewItem: %d\n\n", newIt->data);
//if *head is NULL, make it point to item
if(*head == NULL)
{
*head = newIt; //set head to address of item
newIt->next = *head;
printf("Again: %p\n\n", *head);
}
//else the list is not empty, add item to end of list
else
{
item * iterate = NULL;
iterate = *head;
printf("it: %p head: %p\n\n", iterate, *head);
/*while (iterate->next != *head)
{
iterate = iterate->next;
}
iterate->next = newIt;
newIt->next = *head;*/
}
}
这里是.c文件我写的测试功能:
#include "q.h"
#include <stdio.h>
int main()
{
item i1;
i1.data = 1;
item i2;
i2.data = 2;
item i3;
i3.data = 3;
item * headTemp;
initQueue(&headTemp);
addQueue(&headTemp, i1);
printf("HEAD: %d\n", headTemp->data);
addQueue(&headTemp, i2);
printf("HEAD: %d\n", headTemp->data);
addQueue(&headTemp, i3);
return 0;
}
,输出是:
NewItem: 1
Again: 0x7fff2252eb10
HEAD: 1
NewItem: 2
it: 0x7fff2252eb10 head: 0x7fff2252eb10
HEAD: 2
NewItem: 3
it: 0x7fff2252eb10 head: 0x7fff2252eb10
Segmentation fault
我创建了三个项目插入到队列中。第一个没有问题。但是,当我插入第二个项目时,我遇到了问题。 headTemp->数据应该保持不变,不管我放入队列中的数据是什么,然而它从1到2到3,这是我创建的所有项目的数据。我不确定问题是什么,答案可能会让我盯着我。但我真的很感谢一些帮助。
干杯!
感谢张贴糊能够代码。刚出门,这是错误的:
item * newIt = newItem();
newIt = &item_p;
这是一个直接的内存泄漏。更换地址的地址是一个按值自动变量。因此,即使评估地址将会无效,只要此功能完成,更少的解除引用。
接下来,您需要用有效状态填充节点,为全部为成员变量。你如何做到这一点取决于你,但最简单的方法是在节点创建代码中。要真正做到这一点,你的节点创建代码应该是一个“工厂”功能。即它应该采用初始化节点所需的参数。所以,这样做第一:
item* newItem(int data)
{
item * node = malloc(sizeof(item));
if (item == NULL)
{
perror("failed to allocate node.");
exit(EXIT_FAILURE);
}
node->data = data;
node->next = node->prev = NULL;
return node;
}
一旦你有一个坚实的,你可以修改你addQueue
做到这一点:
void addQueue(item** head, int data)
{
item *prev = NULL;
while (*head)
{
prev = *head;
head = &prev->next;
}
*head = newItem(data);
(*head)->prev = prev;
}
此代码是尚客从一个deque的一个途径。你需要两个指针来做到这一点,保持它们的最佳位置是在一个单独的结构中,以及一个计数来进行大小查询O(1)。正确完成,插入是完整的deque O(1),但你最终会到达那里。
无论如何,更新主要下方出现使得它在测试中的一切。最终,你想有一个弹出式functoin等
int main()
{
item *q = NULL;
for (int i=1; i<=20; ++i)
addQueue(&q, i);
item *p = q;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return 0;
}
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
非常感谢。这帮了很多。 –
您的addQueue()
功能不适用。
void addQueue(item ** head, item item_p){
28 //create new item
29 item * newIt = newItem();
30 newIt = &item_p;
31 printf("NewItem: %d\n\n", newIt->data);
32
33 //if *head is NULL, make it point to item
34 if(*head == NULL)
35 {
36 *head = newIt; //set head to address of item
37 newIt->next = *head;
38 printf("Again: %p\n\n", *head);
39 }
在此你newItem()
获得新分配的节点,但是你再它,因为你不使用分配的内存重新分配给&itemp_p
上线30这是不好的,但在申报项目的变量i1, i2, i3
main()
。
此外,在newItem()
设置next
和prev
到NULL
17 item * newItem(){
18
19 item * node = malloc(sizeof(item));
if(node) { //You can use calloc too.
node->next = NULL;
node->prev = NULL;
}
20 return node;
21 }
不要传递结构作为参数。使用指针。 – Havenard
请,***请***不要编号你的线。切割粘贴测试代码是完全没有价值的。如果您必须提醒注意特定错误的行,请添加一条说明“THIS IS LINE ###”的注释。这就是说,当我严重试图仅仅基于海报小于1K的代表**和**正确*不*铸造'malloc()'(好工作,顺便说一句)。 – WhozCraig
查看你的代码,看看你是否可以找到你的新节点的位置,如果没有设置为以前的有效地址,那么'next'和'prev'指针就被初始化为NULL。你也会在前两行的'addQueue'方法中立即泄漏内存。这不是java。你的代码将一个自动变量推入你的队列中,一旦你的函数返回,它就会失效。 – WhozCraig