-3

I've been learning Data Structure and Algorithm in C and I just got a problem when chaning the order of the elements of a struct

Here is my lib.h file:

    typedef struct ElementType
    {
        int id;
        char name[20];
    } ElementType;


    typedef struct Node
    {
        ElementType data;

        struct Node* left;
        struct Node* right;
    } Node;


    Node* insert(Node** tree, ElementType e)
    {
        if( (*tree) == NULL )
        {
            (*tree)=(Node*)malloc(sizeof(Node));

            (*tree)->data = e;

            (*tree)->left = NULL;
            (*tree)->right = NULL;

            return (*tree);
        }

        else if ((*tree)->data.id == e.id)
            return (*tree);

        else if (e.id < (*tree)->data.id)
            return insert( &((*tree)->left), e);

        else
            return insert( &((*tree)->right), e);
    }

    void freeTree(Node* tree)
    {

        if((tree) == NULL)
            return;

        else
        {
            freeTree(tree->left);
            freeTree(tree->right);

            free(tree);
        }
    }

    void inorder(Node* tree)
    {
        if(tree!=NULL)
        {
            inorder(tree->left);

            printf("%d - %s\n", tree->data.id, tree->data.name);
            printf("This node  : %p\n", tree);
            printf("This data  : %p\n", &(tree->data));
            printf("This left  : %p\n", tree->left);
            printf("This right : %p\n", tree->right);

            inorder(tree->right);
        }
    }


    void init(Node** tree)
    {
        (*tree) = NULL;
    }

Here's my main file included the above lib

ElementType makeNewElem(int a, char* b)
{
    ElementType e;
    e.id = a;
    strcpy(e.name, b);

    return e;
}

int main() {

    Node* root;

    init(&root);
    ElementType a = makeNewElem(5, "A");
    ElementType b = makeNewElem(6, "B");
    ElementType c = makeNewElem(7, "C");

    insert(&root, a);
    insert(&root, b);
    insert(&root, c);

    inorder(root);
    printf("\n");
    freeTree(root);
    inorder(root);
    return 0;
}

Here's the result after I compiled

5 - A
This node  : 0x1671010
This data  : 0x1671010
This left  : (nil)
This right : 0x1671040
6 - B
This node  : 0x1671040
This data  : 0x1671040
This left  : (nil)
This right : 0x1671070
7 - C
This node  : 0x1671070
This data  : 0x1671070
This left  : (nil)
This right : (nil)

23531568 - 
This node  : 0x1671010
This data  : 0x1671010
This left  : (nil)
This right : 0x1671040
23531616 - 
This node  : 0x1671040
This data  : 0x1671040
This left  : (nil)
This right : 0x1671070
0 - 
This node  : 0x1671070
This data  : 0x1671070
This left  : (nil)
This right : (nil)

Then after I move the line "ElementType data;"

typedef struct Node
{
    struct Node* left;
    struct Node* right;

    ElementType data;
} Node;

The console >>

5 - A
This node  : 0x1226010
This data  : 0x1226020
This left  : (nil)
This right : 0x1226040
6 - B
This node  : 0x1226040
This data  : 0x1226050
This left  : (nil)
This right : 0x1226070
7 - C
This node  : 0x1226070
This data  : 0x1226080
This left  : (nil)
This right : (nil)

Segmentation fault (core dumped)

Could someone help me explain why 1. Before I changed the code, why it still printed out the value of data (I though the node would be NULL after being free-ed !?) 2. After I changed the code, why I got core-dumped ?

I am so sorry for my long question and my bad English !

hungdoansy
  • 436
  • 4
  • 10
  • [Please see this discussion on why not to cast the return value of malloc() and family in C..](https://stackoverflow.com/q/605845/2173917) – Sourav Ghosh Jun 01 '17 at 06:16
  • 3
    Undefined behavior is undefined. – melpomene Jun 01 '17 at 06:18
  • 3
    Changing the order of struct members should have no effect on a correct program. If it's causing an error, you probably have undefined behavior somewhere in the program. Use a debugger to step through the program to see when things are wrong. – Barmar Jun 01 '17 at 06:19
  • You never have id 23531568 in your code so the fact that it is in the output says undefined behavior, and as @melpomene says... (or in other words, you're lucky it ran the first time) also: why didn't you pick up the unexpected outputs before you started moving stuff in structs? – John3136 Jun 01 '17 at 06:20
  • 3
    You are freeing your tree and then you call `inorder(root);` right after. So what do you expect? – Jabberwocky Jun 01 '17 at 06:21
  • In the first time, I thought the console would print out nothing after I retried to print inorder the tree because the tree was free-ed (-> Then Each node became NULL, I had a if condition to check if the node is NULL or not) – hungdoansy Jun 01 '17 at 06:24
  • `free(x)` can't set `x`. C uses call-by-value. – melpomene Jun 01 '17 at 06:29
  • `freeTree(root)` correctly frees your tree, but after the call, to `freeTree(root)`, `root` is not `NULL`. You should modify `freeTree` so that its signature is `void freeTree(Node** tree)` and call `freeTree(&root)`, just like you've done it with `insert`. And learn how to use your debugger, this helps greatly to identify problems like that. – Jabberwocky Jun 01 '17 at 06:31
  • @MichaelWalz I did exactly as you said but the console once again printed out exactly as before calling 'freeTree(&root);' – hungdoansy Jun 01 '17 at 06:36
  • 3
    @dOshu Did you change `freeTree()` so it does `*tree =NULL;`? – Barmar Jun 01 '17 at 06:39
  • @Barmar Yep, of course after adding that code, It printed out as I expected. But if I changed freeTree as Michael said and didnt add `*tree =NULL` , It printed out 5 6 7 again ... :/ – hungdoansy Jun 01 '17 at 06:44
  • @dOshu it works great here, you forgot `*tree =NULL;` at the end of your new `freeTree` function. Use your debugger! – Jabberwocky Jun 01 '17 at 06:44
  • @dOshu accessing freed memory is _undefined behaviour_ (google that term), anything can happen. – Jabberwocky Jun 01 '17 at 06:45
  • 1
    @dOshu But that was the whole point of his suggestion -- `freeTree` needs to set the tree to NULL so that `inorder()` won't try to print the freed entries. – Barmar Jun 01 '17 at 06:46
  • I intended to remove that code but Please tell me why I have to add that code !? – hungdoansy Jun 01 '17 at 06:46
  • Sigh.... undefined behaviour is undefined.... – Jabberwocky Jun 01 '17 at 06:47
  • Oh... Anything can happen :D Thanks men. I think I got what I expected :D – hungdoansy Jun 01 '17 at 06:48

1 Answers1

0
...
freeTree(root);
inorder(root);
...

What did you expect here ? This causes an undefined behaviour : sometimes it might work, sometimes it might not.

Remove that freeTree statement and it will work fine.

MikaDo-
  • 43
  • 2
  • 6