2015-02-24 76 views
0

我在C程序中遇到了一个函数问题。该计划的目的是:从二进制文件如何在二进制树中释放分配的内存C

  • 读整数到一个数组
  • 排序使用二叉树这些数字
  • 做一些其他的东西
  • 免费您在使用分配的所有内存的malloc();

我已经得到了一切工作,除了能够释放我的二叉树。这里是我的结构树和节点(又名叶)。

typedef struct Node *NodeP; 
typedef struct Tree *TreeP; 

// Definition of a tree 
    struct Tree 
    { 
     NodeP root; 
    }Tree; 

    // Definition of a node 
    struct Node 
    { 
     int data; 
     NodeP L, R; 
    }Node; 

在我的程序中,我用malloc为我的树和每个单独的节点分配内存。所以我调用一个函数来释放树及其所有节点。

/* 
* Frees the memory allocated for 
* each node 
*/ 
void freeNode(NodeP p) 
{ 
    if(p == NULL) return; 
    freeNode(p->L); 
    freeNode(p->R); 
    free(p); 
} 

/* 
* Frees the memory allocated 
* for the tree 
*/ 
TreeP freeTree(TreeP tree) 
{ 
    if(tree->root == NULL) 
     free(tree); 
    else 
    { 
     freeNode(tree->root); 
     free(tree); 
    } 

    return NULL; 
} 

当我运行这个程序时,我的调试器给我这个错误。

EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 

我已经尝试过精神上经历递归的每次迭代,我找不到为什么它给了我一个错误。我认为它在边缘情况下从树的边缘掉下来了?我不确定。任何帮助是极大的赞赏!

编辑:

这是一个链接,下载完整的程序。我包括一个自述文件和我正在使用的二进制文件。一个只有10个整数,另一个是20000个整数。感谢您一直以来的帮助!

https://copy.com/902v0bMv8DtIMUrc

+0

为什么不看看调用堆栈来实现,问题出在哪里? (至少在什么级别) – ars 2015-02-24 20:02:25

+2

我可以看到两个不同寻常的结构('freeNode'中的'p = NULL'和'freeTree'返回NULL],但这些都不应该是你问题的根源(但无论如何,我会摆脱它们)。我怀疑你已经把堆扔到了别的地方,而且只有当你走树解释节点时才会出现问题。在别处看看。 – user590028 2015-02-24 20:06:07

+0

我看不出有什么明显的错误,所以你必须使用调试器和小树来找到问题。该树可能是畸形的,例如,多个父母指向同一个孩子,或者某些指针未正确初始化,但这些类型的问题不在您共享的代码中。注意:'freeNode'结尾的'p = NULL;'行什么都不做,应该被删除。 – user3386109 2015-02-24 20:09:13

回答

3

有困惑在这里:以上

// Definition of a tree 
struct Tree 
{ 
    NodeP root; 
}Tree; 

// Definition of a node 
struct Node 
{ 
    int data; 
    NodeP L, R; 
}Node; 

的定义定义变量,而不是类型!

这里有一个错误:

TreeP newTree() 
{ 
    TreeP tree = (TreeP) malloc(sizeof(TreeP)); 
    tree->root = NULL; 
    return tree; 
} 

它应该阅读TreeP tree = malloc(sizeof(struct Tree));。一个很好的例子,为什么typedef结构指针是一个坏主意。由于树只保存一个指针,这不会引起任何问题,但它应该是固定的。

这里是错误:

/* 
* Creates a new node in the tree 
*/ 
void insertTreeNode(TreeP tree, int data) 
{ 
    NodeP p = tree->root; 
    Boolean b = FALSE; 

    /* Creates a node and tests for errors */ 
    NodeP node = (NodeP) malloc(sizeof(Node)); 
    if(node == NULL) 
     fprintf(stderr, "Memory allocation failed! \n"); 
    else 
    { 
     node->data = data; 
     node->L = NULL; 
     node->R = NULL; 

     /* Inserts in empty tree case */ 
     if(tree->root == NULL) 
      tree->root = node; 
     else 
     { 
      /* Inserts in any other case */ 
      while(p != NULL && b != TRUE) 
      { 
       if(node->data >= p->data) 
       { 
        if(p->R == NULL) 
        { 
         p->R = node; 
         b = TRUE; 
        } 
        else p = p->R; 
       } 
       if(node->data <= p->data) // replace this line with else 
       { 
        if(p->L == NULL) 
        { 
         p->L = node; 
         b = TRUE; 
        } 
        else p = p->L; 
       } 
      } 
     } 
    } 
} 

您必须如果p->data == data新节点链接到左边或节点p的权利,但不能在两个子树。

可能还有其他的错误,但是这个咬人!

+0

非常感谢!这是我做错了。我解决了你提到的其他问题。 :) – Hotsaucejalapeno 2015-02-24 20:41:23

+1

@Hotsaucejalapeno'struct tree * tree = malloc(sizeof(* tree));'是一个合理的选择,或者只是'Tree * tree = malloc(sizeof(* tree));'如果你修正了你的struct拒绝实际声明'Tree'和'Node'类型。祝你好运。 – WhozCraig 2015-02-24 20:42:58

+0

@WhozCraig:我宁愿'Tree * tree = malloc(sizeof(* tree));'样式。将'*'与该类型绑定是容易出错的,正如在经典的“Tree * L,R;'中为其他'TreeP L,R;'是其他原因的糟糕解决方案。 – chqrlie 2015-02-24 20:46:15