C 链表释放后如何打印?
我正在使用以下功能实现一个链表:C 链表释放后如何打印?,c,linked-list,free,C,Linked List,Free,我正在使用以下功能实现一个链表: struct node{ int data; struct node *next; }; struct list{ struct node *head; }; struct list* list_init(){ struct list *lst; lst = malloc (sizeof(struct list)); lst->head = 0; }; list_add(struct list *l, int num){
struct node{
int data;
struct node *next;
};
struct list{
struct node *head;
};
struct list* list_init(){
struct list *lst;
lst = malloc (sizeof(struct list));
lst->head = 0;
};
list_add(struct list *l, int num){
struct node *point;
point = malloc(sizeof(struct node)):
if (&point == NULL){
return 1;
}
else {
point->data = num;
point->next = l->head;
l->head = point;
return 0;
}
};
void list_print(struct list *l){
struct node *point = l->head;
while (point != 0) {
printf("value = %d and next pointer = %p\n", point->data, point->next);
point = point->next;
}
};
void list_cleanup(struct list l*){
struct node *point;
struct node *temp;
while (point != 0);
temp = point;
point = point->next;
free(temp);
}
};
我不明白为什么当我运行主系统时:
int main(int argc, char *argv[]) {
struct list *a;
a = list_init();
list_add(a, 10);
list_add(a, 53);
list_add(a, 66);
list_print(a);
list_cleanup(a);
list print(a);
输出将是:
66 0x10570b0
53 0x1057090
10 (nil)
17133760 0x10570b0
17133728 0x1057090
17122696 (nil)
我了解前3个输出值,它们是链接列表中指针值的值。但是,在循环遍历列表并释放内存后,list_print()stil如何输出正确的指针值和列表的正确长度?释放内存后不应执行此操作。free()
不会删除内存或将内存归零。它使其可用于以后的分配
7.20.3.2-2
free函数导致ptr指向的空间被释放,也就是说,可供进一步分配
但是,如果指针指向无效内存空间,则结果既不是崩溃也不是特定结果,而是未定义的行为:
6.5.3.2-4:
[…]如果为指针指定了无效值,则一元*运算符的行为未定义。87)
Fn 87:
[…]通过一元*运算符取消引用指针的无效值包括空指针、与指向的对象类型不适当对齐的地址以及对象在其生命周期结束后的地址
Fn 83:
83)如果&E是一个有效的指针表达式(其中&E是“address-of”运算符,它生成指向其操作数的指针),则表达式(&E)->MOS与E.MOS相同
因为它是未定义的行为,所以包括正确打印列表在内的所有行为都是标准的
引用自:free()
不删除或零内存。它使其可用于以后的分配
7.20.3.2-2
free函数导致ptr指向的空间被释放,也就是说,可供进一步分配
但是,如果指针指向无效内存空间,则结果既不是崩溃也不是特定结果,而是未定义的行为:
6.5.3.2-4:
[…]如果为指针指定了无效值,则一元*运算符的行为未定义。87)
Fn 87:
[…]通过一元*运算符取消引用指针的无效值包括空指针、与指向的对象类型不适当对齐的地址以及对象在其生命周期结束后的地址
Fn 83:
83)如果&E是一个有效的指针表达式(其中&E是“address-of”运算符,它生成指向其操作数的指针),则表达式(&E)->MOS与E.MOS相同
因为它是未定义的行为,所以包括正确打印列表在内的所有行为都是标准的
引用自:释放内存后,您使该地址对计算机可用(可访问),以便其他程序使用。如果没有程序使用该区域,则意味着不会覆盖该区域,因此在释放该地址之前保持不变。释放内存后,您使该地址可用(可访问)用于计算机,以供其他程序使用。如果没有程序使用该区域,则意味着不会覆盖该区域,因此在幸运地释放该地址之前,该区域保持不变。当你喝完咖啡后,茶杯不会消失,直到服务员把它拿走再使用
free
对传递给它的指针不做任何操作。您的main调用“list\u free(a)”,而您的源文件定义了“list\u cleanup()”--此处不匹配。您正在调用未定义的行为。任何事情都可能发生,包括打印释放数据的值。@WeatherVane或:如果你决定不喝咖啡,咖啡不会自动消失。@Aminegm Awad我的类比是不完美的。也许更好:你租了一所房子,但当你以后把它交回来时,你有一份门钥匙的复印件。你继续使用这所房子,但有一天它被推平进行重建,没有任何警告(因为它不再是你的家)。这只是运气。当你喝完咖啡后,茶杯不会消失,直到服务员把它拿走再使用free
对传递给它的指针不做任何操作。您的main调用“list\u free(a)”,而您的源文件定义了“list\u cleanup()”--此处不匹配。您正在调用未定义的行为。任何事情都可能发生,包括打印释放数据的值。@WeatherVane或:如果你决定不喝咖啡,咖啡不会自动消失。@Aminegm Awad我的类比是不完美的。也许更好:你租了一所房子,但当你以后把它交回来时,你有一份门钥匙的复印件。您继续使用该房屋,但有一天它被推平进行重新开发,没有任何警告(因为它不再是您的家)。free()
可能会删除内存或将其归零。它甚至可以取消映射,使地址甚至无法访问。它可以这样做。这不是标准化的。而且,即使使用指向空闲
d内存的指针值,也有未定义的行为。@AnttiHaapala完全正确。(但是,当然,如果标准要求内存归零,很难说标准会对指向已释放对象的指针说些什么。很可能在这样一个世界中,这种行为不会是未定义的。猜测。)@Aminegm Awad+1是一个很好的答案。为了完整起见,请添加一个指向您引用的资源的链接:)?free()
可以删除内存或将其归零。它甚至可以取消映射,使地址甚至无法访问。它可以这样做。这不是标准化的。而且,即使使用指向空闲
d内存的指针值,也有未定义的行为。@AnttiHaapala完全正确。(但是,当然,如果标准要求内存归零,很难说标准会对指向已释放对象的指针说些什么。很可能在这样一个世界中,这种行为不会是未定义的。猜测。)@Aminegm Awad+1是一个很好的答案。F