我有这段代码:
struct nodo {
char c;
int val;
struct nodo *pizq, *pder;
};
typedef struct nodo NODO;
具有适当的初始化函数:
NODO * crea_nodo_int (int valor )
{
NODO *p;
p = (NODO *)malloc( sizeof( NODO ) );
if (p == NULL )
return NULL;
p -> pizq = NULL;
p -> pder = NULL;
p -> val = valor;
return p;
}
在我的主要功能上:
NODO * test = crea_nodo_int(5);
free(test);
inorder(test);
正如您所看到的,它是二叉树的实现,其中pizq和pder分别是左右子。
但是我发布这个是因为我已经理解了这个' free()'实际上释放内存,我在这里看不到这一点。你看,我创建了值为5的节点测试,然后释放它,然后当我在控制台中按顺序行走时它会打印出来
' 0'并终止。为什么打印0?它不应该直接进入if (p == NULL) return
的情况并终止而不打印任何东西吗?我究竟做错了什么?
这是我的inorder函数代码:
void inorder( NODO *p )
{
if (p == NULL) return;
if( p->pizq != NULL )
inorder(( p->pizq );
// Process root
printf("%d ", p->val );
if( p->pder != NULL )
inorder( p->pder );
}
答案 0 :(得分:4)
free(ptr)
释放指向的内存ptr
,但ptr
仍然指向释放的内存位置,访问此类内存是未定义的行为。
检查this。
请注意,此(
free
)函数不会更改ptr本身的值,因此它仍然指向相同(现在无效)的位置。
因此,只需调用free()
即可使指针成为Dangling Pointer,而不指向相应类型的有效对象。
在致电free(ptr)
后,请按照将指针设置为NULL
ptr = NULL;
这可以防止悬空指针错误。
所以,在你的情况下,你应该 -
free(test);
test = NULL;
答案 1 :(得分:2)
一旦你在某个指针上调用free
,就不允许你在该内存区域做任何事情。因此,您不应该致电inorder
(或者您可以在 free
之前将其称为)。
您的计划有undefined behavior。非常scared。因此,它的行为是不可预测的,无法解释(除非您花费数年时间深入了解实施细节)。
我建议使用几个类似构造函数的函数:
NODE*create_leaf_node(int val);
NODE*create_pair_node(NODE*left, NODE*right);
并编写一个(递归的)类似析构函数的函数(以调用free(n);
结束):
void destroy_node(NODE*n);
当然,我想你的问题中有struct nodo
,
typedef struct nodo NODE;
您的测试程序可能会:
NODE*ntest = create_pair_node(create_pair_node(create_leaf_node(1),
NULL),
create_leaf_node(3));
inorder(ntest);
destroy_node(ntest), ntest = NULL;
(我在最后一个声明中使用comma operator)
然后使用所有警告和调试信息编译您的程序(例如gcc -Wall -Wextra -g
与GCC)。改进它以获得没有警告。 使用调试器 gdb
(可能还有其他工具,例如valgrind)。
BTW,在C you should not cast the result of malloc
中......当perror
失败然后退出程序时,您可能会考虑显示(malloc
)一些错误消息,例如here。< / p>