c中的链接列表指针转换异常。指针从不存在的位置获取地址

时间:2018-08-30 21:08:45

标签: c pointers linked-list singly-linked-list

我编写了一个初学者的链表程序,并从列表中删除了任何指定的节点。 但是在执行此操作时,我无法理解为什么为什么尽管我已经使用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个节点的指针,但它可以干净地执行。 如何?

2 个答案:

答案 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上被调用后访问动态内存是未定义的行为。测试时,它碰巧在您的系统上运行了几次,这一事实不应被视为意味着您的程序是正确的。测试只能显示错误的存在,不能显示错误的存在。