关于指向结构的指针及其工作原理
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
我有这个代码:
#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