2016-12-04 68 views
-1

我試圖在C. N叉樹的實現當運行它,我得到以下錯誤:中止陷阱6的malloc

sibling(1143,0x7fff7e925000) malloc: *** error for object 0x7f946b4032c8: incorrect checksum for freed object - object was probably modified after being freed. 
*** set a breakpoint in malloc_error_break to debug 
Abort trap: 6 

我不能確定是什麼原因造成的錯誤。正如它所說,我似乎正在寫給一個被釋放的對象。但在我的代碼中,我沒有釋放任何分配的內存。我對c很陌生,非常困惑。我試着用gdb進行調試,它說錯誤是由printTree()引起的。主要調用我遞歸地嘗試打印樹的地方。希望你能幫助我理解這個問題:-)。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

typedef struct { 
    char *name; 
    unsigned int utility; 
    unsigned int probability; 
} Child; 

typedef struct { 
    unsigned int level; 
    unsigned int player; 
    unsigned int nChildren; 
    Child *children; 
} Data; 

typedef struct sNaryNode{ 
    Data *data; 
    struct sNaryNode *kid; 
    struct sNaryNode *sibling; 
} NaryNode; 

NaryNode* createNode(Data data){ 
    NaryNode *newNaryNode = malloc(sizeof (NaryNode*)); 
    newNaryNode->sibling = NULL; 
    newNaryNode->kid = NULL; 
    newNaryNode->data = &data; 
    return newNaryNode; 
} 

NaryNode* addSibling(NaryNode* n, Data data){ 
    if(n == NULL) return NULL; 

    while(n->sibling) 
    n = n->sibling; 

    return (n->sibling = createNode(data)); 
} 

NaryNode* addChild(NaryNode* n, Data data){ 
    if(n == NULL) return NULL; 
    else if(n->kid) 
    return addSibling(n->kid, data); 
    else 
    return (n->kid = createNode(data)); 
} 

void printTree(NaryNode* n) { 
    if(n == NULL) return; 

    if(n->sibling) { 
    printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name); 
    printTree(n->sibling); 
    } 
    else if(n->kid) { 
    printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name); 
    printTree(n->kid); 
    } 
    else { 
    printf("The tree was printed\n"); 
    } 
} 


int main(void) { 
    NaryNode *root = calloc(1, sizeof(NaryNode)); 
    Data data; 
    data.level = 1; 
    data.player = 1; 
    data.nChildren = 2; 
    data.children = calloc(data.nChildren, sizeof data.nChildren); 
    data.children[0].probability = 50; 
    data.children[0].utility = 1; 
    data.children[0].name = "Kom med det første tilbud (anchor)"; 
    data.children[1].probability = 50; 
    data.children[1].utility = 1; 
    data.children[1].name = "Afvent modspilleren kommer med første tilbud"; 
    *root = *createNode(data); 
    int i = 0; 
    for(i=0; i<root->data->nChildren; i++) { 
    addChild(root, data); 
    } 

    printTree(root); 
} 
+1

線'data.children =釋放calloc(data.nChildren,的sizeof data.nChildren);'不有道理。 – 2016-12-04 14:04:10

+0

'data.children = calloc(data.nChildren,sizeof data.nChildren)'你確定要sizeof data.nChildren嗎?嘗試'sizeof * data.children'。 – Stargateur

+0

.........'sizeof(Child)' –

回答

3

代碼中存在各種錯誤。

  1. 分配一個不正確尺寸的存儲器塊:

    data.children = calloc(data.nChildren, sizeof data.nChildren);

    data.childrenChild結構的數組,但你分配結構,其大小等於sizeof(unsigned int),由於data.nChildren作爲一個unsigned int

  2. 以一個臨時變量的地址和存儲起來以備以後使用:

    NaryNode* createNode(Data data){ newNaryNode->data = &data; }

    datacreateNode只存在只要功能運行:在這種情況下,你正在服用本地變量data的地址並將其存儲在您要返回供以後使用的結構中。這是一個非常糟糕的想法,因爲這個指針將引用函數返回後不再存在的對象。

    請記住,您不需要在當前代碼中將Data對象的副本傳遞到createNode,因爲在整個程序中實際上只有一個Data對象。因此,您可以將createNode的原型更改爲createNode(Data* data),並傳遞您在main中創建的Data結構的地址。但是,做比這更多的事情,我認爲需要深層複製結構。

  3. 錯誤地管理對象的生命週期。

    NaryNode *root = calloc(1, sizeof(NaryNode)); *root = *createNode(data);

    createNode返回NaryNode*。但是,您從未實際將其分配給NaryNode*,以便稍後可以釋放它。相反,函數返回的對象的指針僅在調用*root = *createNode(data)期間是已知的,並且在以後不可撤銷地丟失。但是,由於取消引用該對象並將其複製到root中,因此保留該對象的內容:但是,從createNode返回的對象本身會丟失且無法恢復,除非指向該對象的指針仍然存在於樹中。

+0

非常感謝你的偉大答案。如何將創建的節點中傳遞的數據存儲到createNode函數中,而不必傳遞傳遞給它的數據的地址?當你說從createNode返回的對象是'從未釋放'時,你是什麼意思?我對c很新,所以請耐心等待,如果這是愚蠢的問題。 :-) – asdasd

+1

@jdoe:見編輯答案。請記住,這些都是初學者的問題,你最好在C上諮詢一本教科書。 –

2

這是另一個問題。此線不用於NaryNode分配空間,但僅用於一個指針到NaryNode:

NaryNode *newNaryNode = malloc(sizeof (NaryNode*)); 
+0

好!我自己錯過了這個。 –