释放结构给出0

时间:2017-10-28 05:56:00

标签: c pointers struct

我有这段代码:

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 );
}

2 个答案:

答案 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 -gGCC)。改进它以获得没有警告。 使用调试器 gdb(可能还有其他工具,例如valgrind)。

BTW,在C you should not cast the result of malloc中......当perror失败然后退出程序时,您可能会考虑显示(malloc)一些错误消息,例如here。< / p>