链表结构中出现SIGSEGV分段错误

3

我已经在C语言中编写了一个非常简单的链表节点结构,其中包含一些通用指针数据和指向下一个节点结构的指针。我有一个函数将会取得一个链表节点,并将其与任何其他链接的节点一起删除。目前,这个函数的实现方式如下:

void freeLinkedList(LinkedListNode *node)
{
   LinkedListNode *currentNode = node;
   LinkedListNode *previousNode = NULL;
   do
   {
        free(currentNode->data);

        previousNode = currentNode;
        currentNode = currentNode->next;

        printf("Freeing node... %s\n", previousNode->name);
        free(previousNode);
        printf("freed it!\n");
    } while (currentNode != NULL);

    printf("Deleted node and all referencing nodes!");
}

这个函数非常简单,它从给定的节点开始遍历,并继续删除指针数据,指向下一个节点(如果有),然后删除前一个节点的内存。这确实按照预期工作...但只在某些情况下。

实际的LinkedList结构看起来像这样:

typedef struct LinkedListNode {
    void *data;
    struct LinkedListNode *next;
    char name[50];
} LinkedListNode;

在像这样动态分配的结构中,该函数可以完美地工作:
LinkedListNode *myNode1 = malloc(sizeof(struct LinkedListNode));
LinkedListNode *myNode2 = malloc(sizeof(struct LinkedListNode));
LinkedListNode *myNode3 = malloc(sizeof(struct LinkedListNode));
strcpy(myNode1->name, "Node1");
myNode1->data = NULL;
myNode1->next = myNode2;

strcpy(myNode2->name, "Node2");
myNode2->data = NULL;
myNode2->next = myNode3;

strcpy(myNode3->name, "Node3");
myNode3->data = NULL;
myNode3->next = NULL;

freeLinkedList(myNode1); // CALLING DELETE FUNCTION HERE

但是,如果我使用的函数所分配的结构体不是在堆内存上,而是在自动堆栈内存中,就像这样:

LinkedListNode myNode1 = {NULL, NULL, "Node1"};
LinkedListNode myNode2 = {NULL, NULL, "Node2"};
LinkedListNode myNode3 = {NULL, NULL, "Node3"};

myNode1.next = &myNode2;
myNode2.next = &myNode3;

freeLinkedList(&myNode1); // CALLING DELETE FUNCTION HERE

这个函数的这一行出现了SIGSEGV - 分段错误

free(previousNode);

这个错误仅在最后一个节点的自由函数中发生,也就是说输出结果会显示:"Freeing node... node3,然后程序崩溃。
但有趣的是,到目前为止,我只在使用上面的示例时遇到过这个错误。如果我再声明一个本地LinkedListNode结构,像这样:
LinkedListNode myNode1 = {NULL, NULL, "Node1"};
LinkedListNode myNode2 = {NULL, NULL, "Node2"};
LinkedListNode myNode3 = {NULL, NULL, "Node3"};
LinkedListNode myNode4 = {NULL, NULL, "Node4"};

myNode1.next = &myNode2;
myNode2.next = &myNode3;

freeLinkedList(&myNode1);

这个函数实际上是有效的,而且按预期执行了所有操作。

我已经尝试了几个小时来思考这可能是为什么,但我只是停滞不前。这是否与我试图释放在堆栈上分配的内存有关?


我想知道为什么释放空数据指针不会导致SEGV。 - LostBoy
如果传递给free的指针为NULL,则根据标准不执行任何操作。 - Uchia Itachi
2
你知道在出错的例子中,你正在尝试释放非动态分配的内存吗? - LostBoy
1
由于未定义的行为,任何事情都有可能发生。在你的情况下它在第三个节点失败了并且对于四个节点有效。但是,在我的情况下它在第一个节点就失败了。 - Uchia Itachi
1
@Bitious:是的!那就是解释。 - Uchia Itachi
显示剩余7条评论
1个回答

2

你是未定义行为的受害者,这是由于释放堆栈内存造成的。 这可能会导致致命错误,有时却似乎是有效的。

已经在此线程中解答了这个问题,应该可以解释清楚。


2
仅供快速参考,基本上释放在堆栈上分配的内存是未定义行为。我所做的产生了非常不可预测的结果,因此不应该这样做。 - CodingBeagle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接