C 链表结构中SIGSEGV分段错误的获取
我在C中创建了一个非常简单的链表节点结构,其中包含一些通用指针数据和指向下一个节点结构的指针。我有一个函数,它将获取一个链表节点,并删除它以及它链接到的任何其他节点。它目前是这样制作的: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
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根本无法完成。