在C.设计一个队列在向队列添加元素时出现Segfault

在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,这是我创建的所有项目的数据。我不确定问题是什么,答案可能会让我盯着我。但我真的很感谢一些帮助。

干杯!

+0

不要传递结构作为参数。使用指针。 – Havenard

+0

请,***请***不要编号你的线。切割粘贴测试代码是完全没有价值的。如果您必须提醒注意特定错误的行,请添加一条说明“THIS IS LINE ###”的注释。这就是说,当我严重试图仅仅基于海报小于1K的代表**和**正确*不*铸造'malloc()'(好工作,顺便说一句)。 – WhozCraig

+0

查看你的代码,看看你是否可以找到你的新节点的位置,如果没有设置为以前的有效地址,那么'next'和'prev'指针就被初始化为NULL。你也会在前两行的'addQueue'方法中立即泄漏内存。这不是java。你的代码将一个自动变量推入你的队列中,一旦你的函数返回,它就会失效。 – WhozCraig

感谢张贴糊能够代码。刚出门,这是错误的:

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 
+0

非常感谢。这帮了很多。 –

您的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, i3main()

此外,在newItem()设置nextprevNULL

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 }