Search code examples
cpointersstructureallocationunions

How to allocate memory for an array of pointers within a structure?


I have these structures:

struct generic_attribute{
    int current_value;
    int previous_value;
};

union union_attribute{
    struct complex_attribute *complex;
    struct generic_attribute *generic;
};

struct tagged_attribute{
    enum{GENERIC_ATTRIBUTE, COMPLEX_ATTRIBUTE} code;
    union union_attribute *attribute;
};

I keep getting segmentation fault errors because I am not allocating memory properly when creating an object of type tagged_attribute.

struct tagged_attribute* construct_tagged_attribute(int num_args, int *args){
    struct tagged_attribute *ta_ptr;
    ta_ptr = malloc (sizeof(struct tagged_attribute));
    ta_ptr->code = GENERIC_ATTRIBUTE;
    //the problem is here:
    ta_ptr->attribute->generic = malloc (sizeof(struct generic_attribute));
    ta_ptr->attribute->generic = construct_generic_attribute(args[0]);
    return  ta_ptr;
}

construct_generic_attribute returns a pointer to a generic_attribute object. I want ta_ptr->attribute->generic to contain a pointer to a generic_attribute object. This pointer to a generic_attribute object is output by the construct_generic_attribute function.

What would be the proper way to do this?


Solution

  • You need to allocate space for the attribute member too.

    struct tagged_attribute* construct_tagged_attribute(int num_args, int *args)
    {
        struct tagged_attribute *ta_ptr;
        ta_ptr = malloc(sizeof(struct tagged_attribute));
        if (ta_ptr == NULL)
            return NULL;
        ta_ptr->code = GENERIC_ATTRIBUTE;
        ta_ptr->attribute = malloc(sizeof(*ta_ptr->attribute));
        if (ta_ptr->attribute == NULL)
         {
            free(ta_ptr);
            return NULL;
         }
        /* ? ta_ptr->attribute->generic = ? construct_generic_attribute(args[0]); ? */
        /* not sure this is what you want */
    
        return  ta_ptr;
    }
    

    and you should not malloc() for the attribute and then reassign the pointer, in fact your union should not have poitner, because then it doesn't serve any purpose at all, it's a union where both members are pointers.

    This would make more sense

    union union_attribute {
        struct complex_attribute complex;
        struct generic_attribute generic;
    };
    

    so you would set the union value like

    ta_ptr->attribute.generic = construct_generic_attribute(args[0]);