C释放一个实例,该实例由其他指针指向
我有下面的C代码。我有两个指针指向同一个物体。 它说双重自由错误。有人能帮忙看看问题出在哪里吗?谢谢C释放一个实例,该实例由其他指针指向,c,pointers,free,C,Pointers,Free,我有下面的C代码。我有两个指针指向同一个物体。 它说双重自由错误。有人能帮忙看看问题出在哪里吗?谢谢 #include <stdlib.h> #include <stdio.h> typedef struct edge { int head; } edge_t; typedef struct edge_list_t { edge_t *edge; } edge_list_t; int main() { edge_list_t *p1;
#include <stdlib.h>
#include <stdio.h>
typedef struct edge {
int head;
} edge_t;
typedef struct edge_list_t {
edge_t *edge;
} edge_list_t;
int main() {
edge_list_t *p1;
edge_list_t *p2;
edge_t *c;
p1 = malloc(sizeof(edge_list_t));
p2 = malloc(sizeof(edge_list_t));
c = malloc(sizeof(edge_t));
p1->edge = c;
p2->edge = c;
free(c);
if (p2->edge) {
printf("not freed\n");
free(p2->edge);
} else {c
printf("freed\n");
}
return 1;
}
#包括
#包括
typedef结构边缘{
int头;
}边缘;
类型定义结构边缘列表{
边缘_t*边缘;
}边缘列表;
int main(){
边缘列表*p1;
边缘列表*p2;
边缘t*c;
p1=malloc(sizeof(edge_list_t));
p2=malloc(sizeof(edge_list_t));
c=malloc(sizeof(edge_t));
p1->边缘=c;
p2->edge=c;
免费(c);
如果(p2->边缘){
printf(“未释放\n”);
自由(p2->边缘);
}else{c
printf(“释放的\n”);
}
返回1;
}
^最后一个免费
是双免费
。请记住,在第一次调用free
后,c
的值无效。此处:
p2->edge = c;
free(c);
当您释放c
时,c
的值不会改变,即使这样,p2->edge
的值也会保持不变。它当然会保持c的原始值。
因此,您总是释放c
和p2->edge
这两个值都相同的值
为了避免这种情况,如果调用free()
,然后选中if(c)
,则将c
设置为NULL,这将再次返回false和not freec
注意:free()不会以任何方式更改指针。它相信指针指向的是以前从未释放过的正确内存()d。一旦将
c
的控制权转移到p1
,就不应该释放p1
和p2
共享一个边缘指针,您应该通过一个同时释放边缘指针的函数来释放p1
和p2
。这些观察结果导致:
#include <stdio.h>
#include <stdlib.h>
typedef struct edge
{
int head;
} edge_t;
typedef struct edge_list_t
{
edge_t *edge;
} edge_list_t;
// Will acquire a loop when you have an actual list of edges
static void free_edge_list(edge_list_t *e)
{
free(e->edge);
free(e);
}
int main(void)
{
edge_list_t *p1;
edge_list_t *p2;
edge_t *c;
p1 = malloc(sizeof(edge_list_t));
p2 = malloc(sizeof(edge_list_t));
c = malloc(sizeof(edge_t));
p1->edge = c;
c = malloc(sizeof(edge_t));
p2->edge = c;
free_edge_list(p1);
free_edge_list(p2);
return 0;
}
#包括
#包括
typedef结构边缘
{
int头;
}边缘;
类型定义结构边缘列表
{
边缘_t*边缘;
}边缘列表;
//当您有一个实际的边列表时,将获取一个循环
静态无空洞边缘列表(边缘列表)
{
自由(e->边缘);
免费(e);
}
内部主(空)
{
边缘列表*p1;
边缘列表*p2;
边缘t*c;
p1=malloc(sizeof(edge_list_t));
p2=malloc(sizeof(edge_list_t));
c=malloc(sizeof(edge_t));
p1->边缘=c;
c=malloc(sizeof(edge_t));
p2->edge=c;
自由边列表(p1);
自由边列表(p2);
返回0;
}
通常,您应该检查内存分配是否成功;这段代码(仍然)不会这样做。
释放
释放内存块不会将指向该块的指针设置为NULL。分配三个块,释放其中一个块两次。那不好。欢迎来到堆栈溢出。请尽快阅读这篇文章。}else{c
中的c
是不需要的入侵者。请注意,main()
程序通常在成功时返回0和1(或任何非零值)表示某种失败。但除此之外,您已经创建了一个简洁的问题-做得好。@OP:也许您想看看的概念是,这是您所追求的吗?您能告诉我如何设置if条件以避免第二次空闲吗?谢谢。if(p2->edge!=c)free(p2->edge)
@user2529913p2->edge=NULL;
在free(c)之后;
@DavidSchwartz在free(c)
之后,c
值是一个无效的地址,因此表达式p2->edge!=c
在技术上是未定义的行为。我认为问题有三个方面(或者,从一个角度看问题就有三个问题):(1)一旦将c
的控制权转移到其中一个结构,代码就不应执行free(c);
;以及(2)代码不应让p1
和p2
共享c
,以及(3)代码应该通过释放p->edge
元素和主结构的函数来释放p1
和p2
。我添加了free(p2->edge),if条件仍然进入第二个自由路径。free(c);free(p2->edge);if(p2->->edge){printf(“not freed\n”);free(p2->->edge);}else{printf(“freed\n”);}C不能保护你不被射中自己的脚;它假设你知道你瞄准的是危险的武器,并且你有充分的理由在身体的末端打洞。这意味着它不会溺爱初学者,初学者可以在你学习语言时尝试。当你这样做时,free(p2->edge)
,释放由p2->edge
指向的内存。现在p2->edge
指向您已释放的内存,那么为什么要再次释放它呢?如果(p2->edge)
与相同,如果(p2->edge!=NULL)
p2->->->->edge
不为NULL,则指向您已释放的内存。
#include <stdio.h>
#include <stdlib.h>
typedef struct edge
{
int head;
} edge_t;
typedef struct edge_list_t
{
edge_t *edge;
} edge_list_t;
// Will acquire a loop when you have an actual list of edges
static void free_edge_list(edge_list_t *e)
{
free(e->edge);
free(e);
}
int main(void)
{
edge_list_t *p1;
edge_list_t *p2;
edge_t *c;
p1 = malloc(sizeof(edge_list_t));
p2 = malloc(sizeof(edge_list_t));
c = malloc(sizeof(edge_t));
p1->edge = c;
c = malloc(sizeof(edge_t));
p2->edge = c;
free_edge_list(p1);
free_edge_list(p2);
return 0;
}