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);

这个错误只发生在最后一个节点的 free 函数上,也就是说,输出会说: “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);

该功能实际上可以工作,并且按预期执行所有操作。

我已经尝试了几个小时来思考为什么会这样,但我只是被难住了。这与我试图释放堆栈上分配的内存有关吗?

4

1 回答 1

2

您是其中的受害者,Undefined behavior原因是freeing of stack memory. 这可能被证明是致命的,有时似乎有效。

堆栈内存上的这个线程 free() 已经回答了这个问题,应该解释这一切。

于 2013-08-03T00:05:44.693 回答