Search code examples
cstructsegmentation-faultcallocnfa

Calloc error on struct pointer of pointer


I have a problem with my calloc but i can't figure out why. Here is my code:

void ens_init(ensemble* node, ullong value, uint i){
  // *node = malloc(sizeof(struct ensemble)); # Doesn't work
  // *node = calloc(1, sizeof(struct ensemble)); # Doesn't work
  node = calloc(1, sizeof(struct ensemble));
  if (*node == NULL){
    printf("Caloc error\n");
    exit(-1);
  }
  (*node)->key = value;
  (*node)->index = i;
  (*node)->left = NULL;
  (*node)->right = NULL;
}

Here is my ensemble struct:

typedef unsigned int uint;
typedef unsigned long long int ullong;

struct ensemble{
  ullong key;
  uint index;
  struct ensemble* left;
  struct ensemble* right;
};
typedef struct ensemble* ensemble;

In working on non-deterministic finite automate (NFA or AFN in French) and that's why i use this kind of struct. My teacher want to program a function that will determinate a NFA and in this function we have to use a tree.

Here is how i call this function to test it

int main(int argc, char *argv[]){
  ensemble B = NULL;

  ens_ajouter(&B, 5, 1);

  return 0;
}

Thanks for the help :)


Solution

  • You try to call the function ens_ajouter() before calling your initilization function ens_init(). This means that the function calloc() is never called from the main() function.

    I think you are making a mistake to hide the fact that the type ensemble is a pointer to a struct ensemble. This makes your code unreadable.

    I would suggest that you change your typedef to this:

    typedef struct ensemble ensemble;
    

    Or, even better, don't use a typedef at all. It is perfectly fine to have this kind of code:

    #include <stdlib.h>
    #include <stdio.h>
    
    typedef unsigned int uint;
    typedef unsigned long long int ullong;
    
    struct ensemble {
        ullong key;
        uint index;
        struct ensemble* left;
        struct ensemble* right;
    };
    
    void ens_init(struct ensemble** node, ullong value, uint i) {
        *node = calloc(1, sizeof(struct ensemble));
        if (*node == NULL){
            printf("Calloc error\n");
            exit(-1);
        }
        (*node)->key = value;
        (*node)->index = i;
        (*node)->left = NULL;
        (*node)->right = NULL;
    }
    
    int main(void) {
        struct ensemble B;
        struct ensemble* pointer_to_B;
        pointer_to_B = &B;
        ens_init(&pointer_to_B, 5, 1);
    
        return 0;
    }
    

    Why? Because it allows you to see that there is a big problem in your allocation call. In ens_init(), you allocate a memory area large enough to hold a struct ensemble and then you store the address of this area in a pointer to a pointer to a struct (instead of a pointer to a struct). And you didn't even create a local variable of type struct ensemble in the main() function (I fixed that). You should write this instead (notice the asterisk):

    void ens_init(struct ensemble** node, ullong value, uint i) {
        // Asterisk added:
        *node = calloc(1, sizeof(struct ensemble));
        if (*node == NULL){
            printf("Calloc error\n");
            exit(-1);
        }
        (*node)->key = value;
        (*node)->index = i;
        (*node)->left = NULL;
        (*node)->right = NULL;
    }
    

    Ii is strange that you have pointers to a pointer to a struct everywhere. You should avoid that if it is not necessary.