gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Solved: Struct memory problems

#146818 - Rajveer - Sun Dec 09, 2007 6:21 pm

I have a few structs which work fine, and a few which dont. The following works:

Structs:

Code:
struct ObjVertex
{
   v16 x, y, z;
};

struct ObjNormal
{
   v10 x, y, z;
};   

struct ObjTexCoord
{
   t16 u, v;
};

struct ObjTriangle
{
   int Vertex[3];
   int Normal[3];
   int TexCoord[3];
};

struct ObjTexture
{
   int texture;
   e.t.c.
};

struct ObjModel
{
   int nVertex, nNormal, nTexCoord, nTriangle;
   int transform[3];
   int scale;
   
   struct ObjVertex* VertexArray;
   struct ObjNormal* NormalArray;
   struct ObjTexCoord* TexCoordArray;
   
   struct ObjTriangle* TriangleArray;
   
   struct ObjTexture* Texture;
};

struct Ship
{
   Stats...
   struct ObjModel* Model; //Ship's loaded 3D model
};


Allocate:
Code:
struct Ship* ret;   
   
   // the returned model struct, allocate and clear
   ret = calloc(1,sizeof(struct Ship));
   memset(ret, 0, sizeof(struct Ship));


The following doesn't work:

Code:

struct SplineNode
{
   some variables, pointers
};

struct ProgressQuad
{
   some variables
};

struct PositionalLight
{
   light stuff
};

struct TrackModel
{
   struct ObjModel* Model;
   s8 type; // 0 = No Collision, 1 = Collision, 2 = Healing Zone
};

struct Track
{
   int nTrackModel, nSplineNode, nProgressQuad, nLight;
   
   struct ObjModel* LowPolyModel;
   struct TrackModel* TrackModelArray;
   struct SplineNode* SplineArray;
   struct ProgressQuad* ProgressQuadArray;
   struct PositionalLight* LightArray;
};


Allocate:
Code:
struct Track* ret;   
   
   // the returned model struct, allocate and clear
   ret = calloc(1,sizeof(struct Track));
   memset(ret, 0, sizeof(struct Track));

   .
   .
   .

   ret->TrackModelArray = malloc(sizeof(struct TrackModel)*ret->nTrackModel);
   ret->TrackModelArray[nM]->Model = ObjLoadModel(file_Location,(int)temp_Variable[0],(int)temp_Variable[1]); //ObjLoadModel works fine, so thats not the problem



With the latter, after trying to allocate Track arrays or modify variables such as ret->nTrackModel, nothing happens. If I use malloc instead of calloc, the variables have some (incorrect) values. Also, the last line as well as any call to ret->TrackModelArray or any other array pointers, produces an "error: invalid type argument of '->'" error. Any ideas?


Last edited by Rajveer on Mon Dec 10, 2007 1:17 am; edited 1 time in total

#146819 - Dark Knight ez - Sun Dec 09, 2007 6:46 pm

When you use an array index like that... you should use . instead of ->, as you're not dealing with a pointer anymore but with a value (at that specific location).

So ret->TrackModelArray[nM].Model would make more sense.

Small example to clarify...
Code:
int someArray[2];
someArray[0] = 6;
someArray[1] = 8;
printf("%i", someArray[0]); // will output 6


In the above example, you can clearly see an index-use gives you a value, not a (integer) pointer to the value.
_________________
AmplituDS website

#146826 - gmiller - Sun Dec 09, 2007 8:54 pm

I assume that by the time you execute:

Code:

ret->TrackModelArray = malloc(sizeof(struct TrackModel)*ret->nTrackModel);


That ret->nTrackModel is non zero? If it is zero then there are issues that the malloc will allocate zero bytes.

BTW: If you use calloc then:
Code:

memset(ret, 0, sizeof(struct Track));


is not needed ... calloc does clear the heap data to all zero(s).

#146840 - Rajveer - Sun Dec 09, 2007 11:24 pm

Dark Knight ez wrote:
When you use an array index like that... you should use . instead of ->, as you're not dealing with a pointer anymore but with a value (at that specific location).

So ret->TrackModelArray[nM].Model would make more sense.


Even though TrackModelArray is still a pointer to a struct, just like ret is a pointer to a struct? I thought . should be used only if the variable or whatever is defined within the struct. So because I'm allocating an array of TrackModel instead of just one, then the pointer TrackModelArray wouldn't use ->?

gmiller wrote:
I assume that by the time you execute:

Code:

ret->TrackModelArray = malloc(sizeof(struct TrackModel)*ret->nTrackModel);


That ret->nTrackModel is non zero? If it is zero then there are issues that the malloc will allocate zero bytes.


Yup, the idea is that the number of obj models in a level is counted from a text file and stored in nTrackModel, and then nTrackModel TrackModels are allocated. So I have some code in between creating ret and the malloc of size TrackModel*nTrackModel, where the nTrackModel is incremented. Although at the moment it's not working for some reason :S

#146841 - Dark Knight ez - Sun Dec 09, 2007 11:39 pm

Quote:
Even though TrackModelArray is still a pointer to a struct, just like ret is a pointer to a struct? I thought . should be used only if the variable or whatever is defined within the struct. So because I'm allocating an array of TrackModel instead of just one, then the pointer TrackModelArray wouldn't use ->?

Look up the use of . and -> if you don't understand them completely. Quite important to use them in a correct manner. It doesn't matter if you're talking about regular variables or structs... pointers are what matter.

Let me give a struct example, so you hopefully understand.

Code:
struct Coordinate {
    int x;
    int y;
}

struct Coordinate  exampleOne[3]; // exampleOne is actually a pointer to an array.
struct Coordinate *exampleTwo;    // exampleTwo is a generic pointer right now.

exampleOne[1].x = 6;         // . notation here because we use [] to get an index of a pointer/array.
exampleTwo = exampleOne + 1; // exampleTwo now POINTS to exampleOne[1], thus being equal to &exampleOne[1].
exampleTwo->y = 4;           // -> notation here because we use a pointer and want to dereference it.


Hope it makes sense now.
_________________
AmplituDS website

#146843 - Rajveer - Sun Dec 09, 2007 11:57 pm

Ahh, great I understood that! Thanks for that, learn something new everyday, or rather escape having to buy C for dummies for an extra day ;) As such both problems are solved, one because of the . and -> mixup and the other because I didn't see an obvious error.

#146845 - sajiimori - Mon Dec 10, 2007 12:35 am

exampleOne is not a pointer to an array -- it is an array. C just happens to use the rule that if you write the name of an array, it will implicitly convert to a pointer to the first element.

The type of exampleOne is Coordinate[3], not Coordinate*. Declaring an array doesn't allocate any pointers.

#146849 - tepples - Mon Dec 10, 2007 3:15 am

sajiimori wrote:
exampleOne is not a pointer to an array -- it is an array.

To emphasize the difference: On ARM7 and ARM9, sizeof(some pointer) will equal 4, just like on i386, but sizeof(some array) will usually be much larger.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.