1

I'm working on a project for school, I must create and put binary trees into a dynamic array. I specify that I'm working on Windows using GCC (GNU compiler).

typedef struct s_node * TN;
struct s_node {
    char * chain; //Name of the tree
    int occ; //Number of occurences
    int ht; //Tree's height
};
typedef struct s_binary_tree * TBA;
struct s_binary_tree {
    TN root;
    TBA stl; //Sub Tree Left
    TBA str; //Sub Tree Right
};

Firstly I'm allocating memory using malloc() to create an array with x square of binary trees and then I'm allocating the memory for the binary trees.

TBA create_Binary_Tree(char * chain, int occ, int number_letters) {
    TBA tree = malloc(sizeof(TBA));
    tree->root = malloc(sizeof(TN));
    tree->root->chain = malloc(sizeof(char) * (number_letters + 1)); //+1 for the '\0'

    *(tree->root->chain) = '\0';
    strcpy(tree->root->chain,chain);
    tree->root->occ = occ;
    tree->root->ht = 1;

    tree->stl = NULL;
    tree->slr = NULL;

    return tree;
}

TBA * create_Array_Binary_Tree(char * fileName) {
    FILE * file;
    file = fopen(fileName,"r");
    if(!file) {
        exit(EXIT_FAILURE);
    }

    int number_letters;
    fscanf(file,"%d",&number_letters); //number_letters is the number of square that I want to allocate
    TBA * arr = malloc(sizeof(TBA) * number_letters);
    char * letter = malloc(sizeof(char) * 256);
    int occ, i;


    for(i = 0; i < number_letters; i++) { //number_letters = 1 in our example
        fscanf(file,"%s %d",letter,&occ);
        *arr = create_Binary_Tree(letter,occ,number_letters);
    printf("--Adr = %p--\n"arr); //Print the adress
        arr++;
    }
    arr -= i; //Reset the arr pointer

    fclose(file);

    return arr;
}

My problem is when I'm calculating the size of the array, the program tells me that the array size x + 38 square.

int size_Array_Binary_Tree(TBA * arr) {
    int sz_arr = 0;

    while(*arr != NULL) {
printf("-T = %d\tAdr = %p-\n",sz_arr,arr); //Print the adress
    sz_arr++;
    arr++;
}

return sz_arr;
}

Terminal :

--Adr = 0000000000951430-- //1 square allocated
-T = 0  Adr = 0000000000951430- //The square allocated
-T = 1  Adr = 0000000000951438- //?
-T = 2  Adr = 0000000000951440- //?
-T = 3  Adr = 0000000000951448- //...
-T = 4  Adr = 0000000000951450-
-T = 5  Adr = 0000000000951458-
-T = 6  Adr = 0000000000951460-
-T = 7  Adr = 0000000000951468-
-T = 8  Adr = 0000000000951470-
-T = 9  Adr = 0000000000951478-
-T = 10 Adr = 0000000000951480-
-T = 11 Adr = 0000000000951488-
-T = 12 Adr = 0000000000951490-
-T = 13 Adr = 0000000000951498-
-T = 14 Adr = 00000000009514A0-
-T = 15 Adr = 00000000009514A8-
-T = 16 Adr = 00000000009514B0-
-T = 17 Adr = 00000000009514B8-
-T = 18 Adr = 00000000009514C0-
-T = 19 Adr = 00000000009514C8-
-T = 20 Adr = 00000000009514D0-
-T = 21 Adr = 00000000009514D8-
-T = 22 Adr = 00000000009514E0-
-T = 23 Adr = 00000000009514E8-
-T = 24 Adr = 00000000009514F0-
-T = 25 Adr = 00000000009514F8-
-T = 26 Adr = 0000000000951500-
-T = 27 Adr = 0000000000951508-
-T = 28 Adr = 0000000000951510-
-T = 29 Adr = 0000000000951518-
-T = 30 Adr = 0000000000951520-
-T = 31 Adr = 0000000000951528-
-T = 32 Adr = 0000000000951530-
-T = 33 Adr = 0000000000951538-
-T = 34 Adr = 0000000000951540-
-T = 35 Adr = 0000000000951548-
-T = 36 Adr = 0000000000951550-
-T = 37 Adr = 0000000000951558-
-T = 38 Adr = 0000000000951560- //?

The size returned should be 1, but it returns 39. Could you please help me?

EDIT : I removed the pointer from types and adapted the rest but the problem still occurs.

typedef struct s_node TN;
struct s_node {
    ...
};

typedef struct s_binary_tree TBA;
struct s_binary_tree {
    TN * root;
    TBA * stl;
    TBA * str;
};

TBA * create_Binary_tree(...) {
    TBA * tree = malloc(sizeof(TBA));
    tree->root = malloc(sizeof(TN));
    ...
    return tree;
}

TBA ** create_Array_Binary_Tree(...) {
    ...
    TBA ** arr = malloc(sizeof(TBA *) * number_letters);
    ...
    for(i = 0; i < number_letters; i++) {
        ...
        arr[i] = malloc(sizeof(TBA));
        arr[i] = create_Binary_Tree(...);
        ...
    }
    ...
    return arr;
}

Any idea?

jean brick
  • 11
  • 2
  • 4
    `TBA tree = malloc(sizeof(TBA));` is obviously broken. You have the same type on the left (declaring the variable `tree`) and the right side (the argument to `sizeof`). Normally this would look like `T *x = malloc(sizeof (T))` (with a pointer on the left-hand side). Don't hide pointers behind typedefs. – melpomene Apr 08 '17 at 11:21
  • 2
    `sizeof (char)` is 1 by definition. – melpomene Apr 08 '17 at 11:22

1 Answers1

1

There are several errors in this program:

TBA create_Binary_Tree(char * chain, int occ, int number_letters) {
    TBA tree = malloc(sizeof(TBA));
    ...
}

TBA is a pointer to a struct. When you allocate sizeof(TBA) you're asking to allocate as much memory as a pointer needs, which is just 4 bytes (32 bit) or 8 bytes (64 bit). You want to allocate space for your struct instead:

TBA tree = malloc(sizeof(struct s_binary_tree));

The same problem here:

tree->root = malloc(sizeof(TN));

should be:

tree->root = malloc(sizeof(struct s_node));

Only TBA * arr = malloc(sizeof(TBA) * number_letters); is actually correct.

Avoid strcpy.

Instead of doing messy pointer arithmetics like arr -= i;, use a second variable where you store either the original pointer or the one you like to modify.

You are not NULL terminating arr. After you allocate it, there may be junk in it. It's best to make sure to fill it with NULLs if you rely on that being a sentinel:

memset(arr, 0, sizeof(TBA) * number_letters);
// Or use `calloc`, `bzero`, ...

This may be the reason your size_Array_Binary_Tree is giving you a strange result.

Community
  • 1
  • 1
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • Avoiding `strcpy` may be a good idea, but the question you linked to is about `strncpy`, which should never be used (and several answers and comments there agree). `strncpy` is not a safer version of `strcpy`. – melpomene Apr 08 '17 at 11:46
  • Technically `memset`ting `arr` to all-bits-zero is not required to produce null pointers. C doesn't require null pointers to have a particular representation (and null pointers of different types can have different bits set). – melpomene Apr 08 '17 at 11:48
  • @melpomene: You're right about `strncpy`, should have picked a better question/answer… can't find one quickly, though. Regarding the null pointers: you're right on that as well but it's irrelevant for a novice programmer as it *is* all zero bits on all machines a typical programmer comes into contact with. Replace it with `for (int i = 0; i < number_letters; ++i) { arr[i] = 0; }` if you want to. – DarkDust Apr 08 '17 at 12:03
  • I change my types, but the problem still occurs. – jean brick Apr 09 '17 at 14:19
  • @jeanbrick: Did you also initialize the memory of `arr` (using `memset` or the `for` loop I mentioned in my comment to melpomene)? – DarkDust Apr 09 '17 at 19:41
  • @DarkDust: memset is not working, arr[i] = 0 don't work because it's not an int array, I tried calloc but nothing change. – jean brick Apr 10 '17 at 13:36