2015-02-24 79 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