循环单链表中的内存释放
Memory Deallocation in Circular Singly Linked List
我目前正在更新我对数据结构的了解。今天我决定看一下链表。我已经完成了单链表和双向链表的基本概念。但是我在用C实现循环单链表的时候遇到了一个小问题
在创建了3个节点的循环单链表并打印层次结构后,我想释放节点的内存。但是,每当我尝试 运行 代码时,都会抛出异常。据我了解,问题与 free(one);
行有关。正如您在我的代码中看到的那样,我什至试图预先断开节点之间的链接。这个问题背后的原因是什么,是因为我以错误的方式释放循环链表中的内存吗?如果没有,应该遵循什么方法来摆脱这个问题?
#include <stdio.h>
#include <stdlib.h>
typedef struct NodeSL nodeSL;
struct NodeSL{
int data;
nodeSL *next;
};
void circularLinkedList();
int main(){
/* Circular Link List Example */
circularLinkedList();
return 0;
}
void circularLinkedList(){
/* Initializing the nodes. */
nodeSL *head,*one,*two,*three;
/* Allocating the memory. */
one=(nodeSL*)malloc(sizeof(nodeSL));
two=(nodeSL*)malloc(sizeof(nodeSL));
three=(nodeSL*)malloc(sizeof(nodeSL));
/* Assigning data values. */
one->data=1;
two->data=2;
three->data=3;
/* Connecting the nodes. */
one->next=two;
two->next=three;
three->next=one;
/* Saving the address of the first node in head. */
head=one;
nodeSL *p;
int flag=1;
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head;
printf("THIS IS AN EXAMPLE OF A CIRCULAR LINKED LIST!\n");
printf("Head has the address %u\n",head);
while (flag) {
printf("Data: %d",p->data);
printf("\tAdress: %u",p);
printf("\tPoints Forward to the Address: %u\n",p->next);
p=p->next;
if(p==one)
{
flag=0;
}
}
printf("\n\n");
/* Deallocating the memory. */
three->next=NULL;
two->next=NULL;
one->next=NULL;
head=NULL;
free(p);
free(two);
free(three);
free(one);
}
您将 head
设置为 one
。然后你设置 p
等于 head
,因此设置 p
等于 one
。那你free(p)
还要free(one)
。所以你释放了一个你已经释放的分配块。
此外,这段代码很神秘:
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head;
为什么分配一个新节点然后将 p
更改为指向 head
并泄漏您刚刚毫无意义分配的节点?您希望 p
指向 head
已经指向的节点,还是希望 p
指向 newly-allocated 节点?拿定主意。
这里可能有两个错误。
p
是head
,head
是one
,释放p
和one
意味着释放指针两次。
/* Saving the address of the first node in head. */
head=one;
- 分配内存泄漏,立即重新分配。
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head; // p is leaked.
我猜你真的想要 p->next = head
。
您正在陷入一些初学者在使用指针时遇到的经典陷阱。
nodeSL *p;
p = malloc(sizeof(nodeSL));
p = head;
// ...
free(p)
您忘记了指针只是一个引用某些内存位置的数字。如果你想使用指针(在本例中,p
)来遍历你的列表,你不需要从系统申请内存。
简而言之,你这里有一个double-free。您释放 p
,然后释放 one
,这与循环后 p
的值相同。如果您使用调试器,您会在这一行看到错误。
此外,您分配了内存,将其存储在 p
中,并通过在 p
中存储不同的值立即 泄漏了 该内存。
所以,不要这样做,你会没事的。
我目前正在更新我对数据结构的了解。今天我决定看一下链表。我已经完成了单链表和双向链表的基本概念。但是我在用C实现循环单链表的时候遇到了一个小问题
在创建了3个节点的循环单链表并打印层次结构后,我想释放节点的内存。但是,每当我尝试 运行 代码时,都会抛出异常。据我了解,问题与 free(one);
行有关。正如您在我的代码中看到的那样,我什至试图预先断开节点之间的链接。这个问题背后的原因是什么,是因为我以错误的方式释放循环链表中的内存吗?如果没有,应该遵循什么方法来摆脱这个问题?
#include <stdio.h>
#include <stdlib.h>
typedef struct NodeSL nodeSL;
struct NodeSL{
int data;
nodeSL *next;
};
void circularLinkedList();
int main(){
/* Circular Link List Example */
circularLinkedList();
return 0;
}
void circularLinkedList(){
/* Initializing the nodes. */
nodeSL *head,*one,*two,*three;
/* Allocating the memory. */
one=(nodeSL*)malloc(sizeof(nodeSL));
two=(nodeSL*)malloc(sizeof(nodeSL));
three=(nodeSL*)malloc(sizeof(nodeSL));
/* Assigning data values. */
one->data=1;
two->data=2;
three->data=3;
/* Connecting the nodes. */
one->next=two;
two->next=three;
three->next=one;
/* Saving the address of the first node in head. */
head=one;
nodeSL *p;
int flag=1;
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head;
printf("THIS IS AN EXAMPLE OF A CIRCULAR LINKED LIST!\n");
printf("Head has the address %u\n",head);
while (flag) {
printf("Data: %d",p->data);
printf("\tAdress: %u",p);
printf("\tPoints Forward to the Address: %u\n",p->next);
p=p->next;
if(p==one)
{
flag=0;
}
}
printf("\n\n");
/* Deallocating the memory. */
three->next=NULL;
two->next=NULL;
one->next=NULL;
head=NULL;
free(p);
free(two);
free(three);
free(one);
}
您将 head
设置为 one
。然后你设置 p
等于 head
,因此设置 p
等于 one
。那你free(p)
还要free(one)
。所以你释放了一个你已经释放的分配块。
此外,这段代码很神秘:
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head;
为什么分配一个新节点然后将 p
更改为指向 head
并泄漏您刚刚毫无意义分配的节点?您希望 p
指向 head
已经指向的节点,还是希望 p
指向 newly-allocated 节点?拿定主意。
这里可能有两个错误。
p
是head
,head
是one
,释放p
和one
意味着释放指针两次。
/* Saving the address of the first node in head. */
head=one;
- 分配内存泄漏,立即重新分配。
p=(nodeSL*)malloc(sizeof(nodeSL));
p=head; // p is leaked.
我猜你真的想要 p->next = head
。
您正在陷入一些初学者在使用指针时遇到的经典陷阱。
nodeSL *p;
p = malloc(sizeof(nodeSL));
p = head;
// ...
free(p)
您忘记了指针只是一个引用某些内存位置的数字。如果你想使用指针(在本例中,p
)来遍历你的列表,你不需要从系统申请内存。
简而言之,你这里有一个double-free。您释放 p
,然后释放 one
,这与循环后 p
的值相同。如果您使用调试器,您会在这一行看到错误。
此外,您分配了内存,将其存储在 p
中,并通过在 p
中存储不同的值立即 泄漏了 该内存。
所以,不要这样做,你会没事的。