访问单链表中的下一个节点时的Segfault

时间:2016-11-01 02:35:28

标签: c linked-list reverse

我试图反转一个单链表,但有点扭曲。它不是将指向下一个节点的指针作为实际的下一个节点,而是指向该下一个节点中的指针。

struct _Node
{
    union
    {
        int n;
        char c;
    } val;
    void *ptr; /* points to ptr variable in next node, not beginning */
    int var;
};
typedef struct _Node Node;

我知道如何扭转正常的单链表,我想我对如何解决这个问题有了一般性的想法,但是当我试图访问{{{}时,我会遇到段错误。 1}}我不知道为什么。

head->ptr

即使我尝试访问Node *reverse(Node *head) { Node * temp; Node * prev = NULL; while(head != NULL) { temp = head->ptr + 4; /* add 4 to pass union and get beginning of next node */ head->ptr = prev; prev = head; head = temp; } return prev; } 而不添加4,我也会遇到段错误。

我对此代码的驱动程序只是一个目标文件,因此我无法查看事件的调用方式或类似内容。我要么错过一些明显的东西,要么在驱动程序中存在问题。

2 个答案:

答案 0 :(得分:1)

首先,我将向您展示代码中的一个主要问题:

    while (head) // is shorter than while(head != NULL)
    {
        // Where does the 4 come from?
        // And even if: You have to substract it.
        // so, definitively a bug:
        // temp = head->ptr + 4; /* add 4 to pass union and get beginning of next node */
        size_t offset_ptr = (char*)head->ptr - (char*)head;
        // the line above should be moved out of the while loop.
        temp = head->ptr - offset_ptr;

无论如何,你的算法可能不会像写的那样工作。如果你想要反转东西,你将不得不倒退(这在单个链接列表中是非常重要的)。有两种选择:

  1. 计算元素数,分配数组,记住该数组中的指针,然后重新分配下一个指针。

  2. 创建一个临时双链表(实际上你只需要另一个反向链表,因为两个列表一起形成一个双链表)。然后再次步行将下一个指针从临时列表复制到旧列表。请记住在返回之前释放临时列表。

答案 1 :(得分:1)

我尝试了你的代码并进行了一些调整,在我看来你的代码有一些逻辑错误。您的指针一次又一次被覆盖(从一个节点跳到另一个节点并返回:1-> 2,2-> 1),这导致了可疑的内存泄漏。在这里,您的代码的工作版本......

Node *reverse(Node *head)
{
    Node *temp = 0;
    //Re-ordering of your assignment statements
    while (head) //No need for explicit head != NULL 
    {
        //Here this line ensures that pointers are not overwritten
        Node *next = (Node *)head->ptr; //Type casting from void * to Node *
        head->ptr = temp;
        temp = head;
        head = next;
    }
    return temp;
}