Search code examples
cpointersstructreferencedynamic-memory-allocation

Reference of pointer to structure inside of structure inside of another structure


Before anything these are the links for the complete code:

Note: Code was fixed. See older versions to look up the incorrect code.

I've been trying to initialize a Vector (like in linear algebra) by referencing it in the arguments like this:

int buildNormalVector(double x, double y, double z, Vector **v)
{
    (*v) = (Vector *)malloc(sizeof(Vector *));
    (*v)->x = x;
    (*v)->y = y;
    (*v)->z = z;
    (*v)->base = (Basis *)malloc(sizeof(Basis *));
    buildSimpleVector(1, 0, 0, &((*v)->base->i));
    buildSimpleVector(0, 1, 0, &((*v)->base->j));
    buildSimpleVector(0, 0, 1, &((*v)->base->k));
    return v;
}

Where the structure of a Vector goes like this:

typedef struct Vector Vector;
typedef struct SimpleVector SimpleVector;
typedef struct Basis Basis;

struct Vector {
    double x;
    double y;
    double z;
    Basis *base;
};

struct Basis {
    SimpleVector *i;
    SimpleVector *j;
    SimpleVector *k;
};

struct SimpleVector {
    double x;
    double y;
    double z;
};

Note this line:

buildSimpleVector(1, 0, 0, &((*v)->base->i));

And here is how I initialize each SimpleVector that will work as a basis:

int buildSimpleVector(double x, double y, double z, SimpleVector **v)
{
    (*v) = (SimpleVector *)malloc(sizeof(SimpleVector *));
    (*v)->x = x;
    (*v)->y = y;
    (*v)->z = z;
    return 0;
}

I've been struggling to find the correct way to pass a reference to the i, j, k vector basis of that vector. I've tried &(*((*v)->base)->k)aswell but to me it is too confusing and it doesn't work. The example above works but only half of the time and gives a read access violation error at this line:

(*v) = (SimpleVector *)malloc(sizeof(SimpleVector *));

Sometimes the program goes through all tests, sometimes it doesn't (which is the strangest part of this issue).

I know for sure that to change the Vector *v that was declared at main has to be passed by reference like Vector **v and then I can do (*v) = malloc and change it.. to change the original one, and that the parentheses is needed due to operators precedence. So is the problem when I pass the reference of the SimpleVector to build it or when I allocate the Vector? Can I do something like this?

Vector *v;
buildNormalVector( 1, 2, 3, &v);

There are probably too many questions about structures, pointers and memory allocation, so if you know any good book to read or internet page that can explain all these concepts I would greatly appreciate it!

Edit:

I've been using Visual Studio 2017 to compile and run the program


Solution

  • You have a consistent problem with memory allocation:

    (*v) = (Vector *)malloc(sizeof(Vector *));
    
    (*v)->base = (Basis *)malloc(sizeof(Basis *));
    
    (*v) = (SimpleVector *)malloc(sizeof(SimpleVector *));
    

    The allocated memory is too small to hold your structures. Change it to:

    (*v) = malloc(sizeof(Vector));
    
    (*v)->base = malloc(sizeof(Basis));
    
    (*v) = malloc(sizeof(SimpleVector));
    

    Also, in your test you never release the allocated memory.

    You should not return pointer as integer in:

    int buildNormalVector(double x, double y, double z, Vector **v)
    (*v) = (Vector *)malloc(sizeof(Vector *));
    //
     return v;
    }
    

    Wrong format "%d" for double x, y, z in

    void displayVector(Vector *v)
    {
        printf("\nVector\n[%8.2lf i ]\n[%8.2lf j ]\n[%8.2lf k ]", v->x, v->y, v->z);
        printf("\nBase\n[%d, %d, %d], [%d, %d, %d], [%d, %d, %d]\n",
            v->base->i->x, v->base->i->y, v->base->i->z,
            v->base->j->x, v->base->j->y, v->base->j->z,
            v->base->k->x, v->base->k->y, v->base->k->z);
    }