关于指向结构的指针及其工作原理

About pointers to structs and how they works

我有这个代码:

 #include <stdio.h>
#include <stdlib.h>

typedef struct node{
    struct node* next;
    int data;
}NODE;
NODE* makeNode (int x){
    NODE* new;
    new = (NODE*)malloc(sizeof(NODE));
    new -> data = x;
    new -> next= NULL;
    return new;
}
typedef NODE* linkedlist;
void insertnode (NODE** node, int x){
    if(!(*node))
        *node=makeNode(x);
    else
        insertnode(&((*node)->next), x);
}
void deletenode(NODE** node){

    (*node)=NULL;
    free (*node);
}
int main()
{
    NODE* node;
    linkedlist mylist;
    mylist=NULL;
    insertnode(&mylist, 3); //insert a node
    insertnode(&mylist, 4);
    node = mylist->next; //
    deletenode(&(mylist->next));
    printf("\n%d\n",node->data); // prints 4
    return 0;
}

我正在研究二叉搜索树,当我到达删除部分时,我开始怀疑指针在内存中的工作方式,我的世界崩溃了。

我将使用这个链表代码而不是 BST 代码,因为对我来说更容易解释我的疑问。

好吧,如果我这样做 node=NULL; mylist 将仍然存在,因为节点是指向 mylist 的指针的副本,但是当我这样做时:

free(node->next);
node->next=NULL; 

mylist->next 将不再存在,因为 node->next 是下一个节点的原始指针。

所以在代码中我在 node

中复制了 mylist->next 指针
node = mylist->next;

我假设是这样的:

mylist-------------->[|data|next|]->[|data|next|]<------------------node;

然后我删除原来的节点。但是当我惊讶地打印 node->date 时,程序打印 4.

我知道指针是保存内存位置的变量。但是我不明白为什么 node->data; 仍然存在,如果我释放节点并设置它 NULL; 只影响指针而不影响内存?

当我释放一个指针并将其设为 NULL 时,该指针持有的内存块会发生什么情况?

我的问题是指向结构的指针,以及它们如何处理由它们指向的分配内存。

我希望我能让我明白,我的英语不太好。

释放后访问内存会调用未定义的行为。 一些可能的结果是:

  • 您可能会得到之前在该地址提交的数据。
  • 您可能会得到零或其他一些值
  • 程序可能会崩溃

但是这个列表并不全面,可能还会发生其他一些情况。

要点是,永远不要从已释放的内存位置访问数据。

指针指向内存位置。

free() 之后,您将分配的内存还给 OS。

访问此内存是 UB(未定义行为)

所以您可能会看到预期的结果,但由于您有 UB,因此不能保证始终如此。

在你的情况下,假设你释放了指针 mylist->next 指向的内存。

free(mylist->next)
mylist->next = NULL;

现在指针mylist->next持有的内存返回给OS。由于此内存可供 OS 使用,因此它可以用它做任何事情。在您的情况下,它现在将 anytihng 写入此位置并保留 free() 之前的内容,因此您返回 4 但是如果此内存用于分配给其他目的,那么您可能没有得到什么如你所愿。

所以基本上访问释放的内存会导致 UB