在这种情况下,malloc如何工作?

时间:2014-08-16 19:15:43

标签: c segmentation-fault binary-tree

以下是我使用gcc -Wall -ansi -g

的程序代码

该程序生成二叉树并按顺序打印。但是我有问题。

我无法使root = NULL并且必须分配内存,我认为应该在NULL上标记。

还有另一个问题。如果没有NULL但是分配了内存,它是如何工作的? malloc是否在NULL上分配(*root) -> right_childleft_child的内存。我完全无法得到它。如果我没有像这样分配内存,就会出现Segmentation故障。欢迎任何帮助和批评。

#include <stdlib.h>
#include <stdio.h>
/*struct for node it has pointers and value*/
struct node {
    struct node *left_child ;
    struct node *right_child;
    int val;
};

/*Prints error message out of memory*/

void outOfMemoryError(void){
    fprintf (stderr,"out of memory error :(\n");
    fflush(stderr); 
    exit (123);
}

/*print tree inorder*/
void printTreeInOrder (struct node **rootNode){
    if ( (*rootNode) == NULL)
    {   
#ifdef DEBUG
        printf("## my node is null");
#endif

        return;
    } 
    if ( (*rootNode)->left_child !=NULL){
        printTreeInOrder( (*rootNode) ->left_child);
    }

    printf ("%d ",(*rootNode) ->val);
    if ((*rootNode)->right_child !=NULL){
        printTreeInOrder((*rootNode)->right_child);
    }
}

/*add node uses recursion*/
void addNode (struct node **root, int value ){
    if ( (*root) == NULL) {
#ifdef DEBUG
        printf("## my root is null\n");
        fflush (stdout);
#endif
        (*root) = malloc (sizeof (struct node));

        if (root == NULL)
            outOfMemoryError();
        (*root) ->val = value;    
        /* I don't know why I have to malloc this memory instead using NULL*/
        (*root) ->left_child = malloc (sizeof (struct node));
        (*root) ->right_child = malloc (sizeof (struct node));
    }
    else if ((*root) ->val > value){
        addNode ((*root)->right_child,value);
    }
    else  
        addNode ((*root)->left_child,value);

}

int main(void)
{   
    /*input vars*/
    char string [80];
    int temp = 0;

    /*root of the whole tree*/
    struct node *root = malloc (sizeof (struct node));

    printf ("i will add to binnary tree as long as int is bigger than 0\n");
    while (1) {
        fgets (string,sizeof(string),stdin);
        sscanf(string,"%d",&temp);
        if (temp <= 0)
            break;
        addNode(root,temp);
    }
    printf("Printing tree Inorder\n");
    printTreeInOrder(root); 
    return 0;
}

3 个答案:

答案 0 :(得分:1)

如果我正确阅读了addNode函数应该执行的操作,那么第一个malloc会出现内存泄漏。

=&GT;您将指针传递给指针struct node(即:struct node* * [注意空格])。因此,addNode应更新struct node*以反映新的根。这就是你需要传递地址的原因(例如:&root)。

我希望addNode使用该指针创建(例如:malloc)一个新的struct node并存储到调用者获取新值。例如:

struct node* root = NULL;

...

addNode(&root, temp);

在addNode中:

    (*root) ->left_child = NULL;
    (*root) ->right_child = NULL;

因为按设计,left_child将是“root”(addNode的第一个arg),它将创建节点。

然后:

   else if ((*root) ->val > value){
        addNode (&((*root)->right_child),value);
   } else {
        addNode (&((*root)->left_child ),value);
   }

如果您未将指针传递给root->left/right_child,则不会更新struct node*的内容。

答案 1 :(得分:0)

当预期参数是Node **时,您正在传递Node *。你需要传递为&amp;节点。在将指针传递给函数之前,必须引用指针。除非你这样做,否则分配不会坚持。

答案 2 :(得分:0)

嗨,大家好,你帮了我很多忙!这段代码正常工作,我用随机生成的测试(和valgrind(释放堆块)来测试它。

#include <stdlib.h>
#include <stdio.h>
/*struct for node it has pointer and value*/
struct node {
    struct node *left_child ;
    struct node *right_child;
    int val;
};

/*prints to stderr with flushing buffor 
 *NOTE: add newline on output
 *NOTE: require -DDEBUG in compilator command*/
void debugPrint(char * string){
#ifdef DEBUG    
    fprintf (stderr,"%s\n",string);
    fflush(stdout);
#endif
}


/*Prints error message out of memory*/

void outOfMemoryError(void){

    fprintf (stderr,"out of memory error :(\n");
    fflush(stderr); 
    exit (123);
}

/*print tree inorder*/
void printTreeInOrder (struct node* *root){
    if ( (*root) == NULL)
    {   
        return;
    } 
    if ( (*root)->left_child !=NULL){
        printTreeInOrder( &(*root) ->left_child);
    }

    printf ("%d ",(*root) ->val);
    if ((*root)->right_child !=NULL){
        printTreeInOrder( &(*root)->right_child);
    }
}

/*add Node uses recursion*/
void addNode (struct node* *root, int value ){
    if ( (*root) == NULL) {
        debugPrint("I'm in null of addnote");
        (*root) = malloc (sizeof (struct node));

        if ((*root) == NULL)
            outOfMemoryError();
        (*root) ->val = value;      

        (*root) ->left_child = NULL;
        (*root) ->right_child = NULL;
        debugPrint("I'm out null of addnote");  
    }
    else if ((*root) ->val > value){
        debugPrint("I'm sending Value to right");
        addNode (&(*root)->right_child,value);
    }
    else { 
        addNode (&(*root)->left_child,value);
        debugPrint("I'm sending Value to left");
    }
}


/*uses postOrder to delete all tree node*/
void deleteTree(struct node* *root){
    if ( (*root) == NULL)
    {   
        return;
    } 
        deleteTree( &(*root) ->left_child);
        deleteTree( &(*root)->right_child);
        free ( *root);
}
int main(int argc, const char *argv[])
{   
    /*input vars*/
    char string [80];
    int temp = 0;

    /*root of the whole tree*/
    struct node *root = NULL;

    printf ("i will add to binnary tree as long as int is bigger than 0\n");
    while (1) {
        fgets (string,sizeof(string),stdin);
        sscanf(string,"%d",&temp);
        if (temp <= 0)
            break;
        addNode(&root,temp);
    }
    printf("Printing tree Inorder\n");
    printTreeInOrder(&root); 
    deleteTree(&root);
    return 0;
}