Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 链表结构中SIGSEGV分段错误的获取_C_Linked List_Segmentation Fault_Heap_Free - Fatal编程技术网

C 链表结构中SIGSEGV分段错误的获取

C 链表结构中SIGSEGV分段错误的获取,c,linked-list,segmentation-fault,heap,free,C,Linked List,Segmentation Fault,Heap,Free,我在C中创建了一个非常简单的链表节点结构,其中包含一些通用指针数据和指向下一个节点结构的指针。我有一个函数,它将获取一个链表节点,并删除它以及它链接到的任何其他节点。它目前是这样制作的: void freeLinkedList(LinkedListNode *node) { LinkedListNode *currentNode = node; LinkedListNode *previousNode = NULL; do { free(currentNo

我在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!");
}
typedef struct LinkedListNode {
    void *data;
    struct LinkedListNode *next;
    char name[50];
} 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);
它非常简单地从函数中给定的节点进行遍历,并继续删除指针数据,指向指向的下一个节点(如果有),然后删除前一个节点的内存。这确实像预测的那样有效。。。但只有在某些情况下

实际的LinkedList结构如下所示:

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!");
}
typedef struct LinkedListNode {
    void *data;
    struct LinkedListNode *next;
    char name[50];
} 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);
在这样动态分配结构的情况下,该函数可以完美地工作:

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);
此错误仅发生在最后一个节点的自由函数处,即输出将显示: “释放节点…节点3

然后崩溃

但非常有趣的是,到目前为止,我只使用上面的示例体验过它。如果我说,请再声明一个本地LinkedListNode结构,如下所示:

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!");
}
typedef struct LinkedListNode {
    void *data;
    struct LinkedListNode *next;
    char name[50];
} 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);
该函数实际工作,并按预期执行所有操作


我已经花了几个小时来思考为什么会这样,但我很困惑。这与我试图释放堆栈上分配的内存有关吗?

您是
未定义行为的受害者,这是由于
释放堆栈内存而导致的。
这可能被证明是致命的,有时似乎有效


这一点在这个线程中已经得到了回答,应该可以解释这一切。

我想知道为什么释放空数据指针与我在读取CPP引用时理解的情况不符,将空指针交给free将毫无用处。您是否知道您正在尝试释放失败的exa中的非动态分配内存MPE?由于未定义的行为,任何事情都可能发生。在您的例子中,它在节点3失败,在4个节点上工作。但是,在我的例子中,它在第一个节点本身失败。@Bitious:是的!这就是解释。为了快速参考,实际上释放堆栈上分配的内存是未定义的行为。我所做的会产生非常不可预测的结果,并且uld根本无法完成。