我编写了一个初学者的链表程序,并从列表中删除了任何指定的节点。 但是在执行此操作时,我无法理解为什么为什么尽管我已经使用free()删除了有问题的节点,但是在该节点之后,我仍如何获得对该节点的引用? 原因代码工作正常,但我不明白为什么? 我还添加了一堆打印语句,以查看发生了什么。 这是代码:
#include <stdio.h>
#include <stdlib.h>
struct node{
int key;
struct node *next;
};
struct node *head = NULL;
void insert_first_node(int val){
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->key=val;
head = temp;
}
void insert(int val){
struct node *temp = (struct node *)malloc(sizeof(struct node));
struct node *s=head;
temp->key=val;
temp->next=NULL;
while(s->next!=NULL)
s=s->next;
s->next=temp;
}
void delete(){
int d;int i;
printf("Enter the position of the node you want to delete\n");
scanf("%d",&d);
struct node *s=head;
for(i=1;i<d-1;i++)
s=s->next;
printf("%d\n",s->key);
printf("%d\n",s->next->key);
printf("%d\n",s->next->next->key);
free(s->next);
printf("%d\n",s->key);
printf("%d\n",s->next->key);
printf("%d\n",s->next->next->key);
s->next=s->next->next;
printf("%d\n",s->key);
printf("%d\n",s->next->key);
printf("%d\n",s->next->next->key);
}
void print(){
struct node *temp =head;
printf ("\n[head] => ");
while(temp!=NULL){
printf("%d => ",temp->key);
temp=temp->next;
}
printf("[end]\n");
}
void main(){
int v;int x;
insert_first_node(10);
for(x=2;x<=10;x++){
insert(x*10);
}
print();
delete();
print();
}
这是输出:
[head] => 10 => 20 => 30 => 40 => 50 => 60 => 70 => 80 => 90 => 100 => [end]
Enter the position of the node you want to delete
4
30
40
50
30
0
50
30
50
60
[head] => 10 => 20 => 30 => 50 => 60 => 70 => 80 => 90 => 100 => [end]
该节点已按预期从列表中删除,但不应删除,因为我从内存中删除了第4个节点,因此程序不应具有指向第5个节点的指针,但它可以干净地执行。 如何?
答案 0 :(得分:0)
如果您访问先前已释放的内存,则您正在调用undefined behavior.
这并不意味着您会得到一个错误,任何事情都可能发生。
正如您所描述的,该程序也可以正常运行,但是您不能依赖该行为。它可能现在可以在您的机器上运行,但在其他时间可能会出错。
答案 1 :(得分:0)
在您NULL
之后立即设置指向动态内存块free
的指针是一种好习惯,以防止出现双重释放的情况(free(NULL)
是良性的)并使任何试图徒劳地访问它。
inline void my_free(void **p)
{
free(*p);
*p = NULL;
}
用法:
void *p = malloc(...);
...
my_free(&p);
在指针free
上被调用后访问动态内存是未定义的行为。测试时,它碰巧在您的系统上运行了几次,这一事实不应被视为意味着您的程序是正确的。测试只能显示错误的存在,不能显示错误的存在。