GP32 Memory Allocation


pea

developer
Joined
Oct 3, 2004
Messages
1,089
Age
46
Location
New Zealand
Website
www.projectitis.com
Hi guys,

I'm sure this has been asked before, but what is the best way to allocate memory for a structure? Let the compiler do it, or do it manually? Are there any differences?

Here is my example:

COMPILER DOES IT (tRGBA)
Code:
typedef struct {
	unsigned char red;
	unsigned char green;
	unsigned char blue;
	unsigned char alpha;
} tRGBA;

typedef struct {
	unsigned char ratio;
	tRGBA color;
} tRecord;


record = (tRecord*)malloc (sizeof(tRecord));

MANUAL (tRGBA)
Code:
typedef struct {
	unsigned char red;
	unsigned char green;
	unsigned char blue;
	unsigned char alpha;
} tRGBA;

typedef struct {
	unsigned char ratio;
	tRGBA *color;
} tRecord;

record = (tRecord*)malloc (sizeof(tRecord));
record->color = (tRGBA*)malloc (sizeof(tRGBA));

Which is best? Is it best to just choose one and always use that? i am going to be creating 'records' and adding them to lists etc.
 
I'd go for the top one (compiler). The other one requires more maintenance on copying etc. It also takes more memory! Pointer + maintenance blocks around malloc manager.

I'd probably do the manual method if I wanted to share tRGBA objects. So I can update one colour and change the colour of n records.

Mark
 
Thanks Mark. re: Compiler handling it, will the following work ok?

Code:
tRecordList *list = createRecordList();

int i;
for (i=0; i<count; i++){
  tRecord record;
  record.ratio = 100;
  record.color.red = 1;
  record.color.green = 2;
  record.color.blue = 3;
  record.color.alpha = 4;

  addRecordToList( list, &record );
}

I've always done it manually because I'm not sure when the compiler will destroy the objects!
 
I believe that will give you the same pointer everytime, so all items will contain whatever you added last.

What you need is:

Code:
int i;
for (i=0; i<count; i++){
 tRecord *record;
record = (tRecord*)malloc (sizeof(tRecord));
record->color.alpha = 4;
//etc//
addRecordToList( list, record );
}
 
Yes, that was my question, Thats the way I do it currently. I just wondered if it could be done somehow where the compielr handles the allocation...
 
pea posted on Oct 6 2005 at 09:14 PM said:
I've always done it manually because I'm not sure when the compiler will destroy the objects!

The objects are put on the top of the stack - a big pile of memory. They are destroyed at the end of scope. This is the end of the block - closing brace.

e.g.
Code:
1:{
2:   int a =1;
3:   {
4:      int b = 2;
5:      {
6:         int c = 3;
7:      }
8:   }
9:}

explanation:
1: start of block
2: push 1 onto stack
3: start of block 
4: push 2 onto stack
5: start of block
6: push 3 onto stack - note that a,b,c are all on the stack now and may all be accessed
7: close of block - 3 is popped from the stack. So c is no longer available
8: close of block - 2 is popped from the stack. So b is no longer available
9: close of block - 1 is popped fom the stack. So a is no longer available

I know these are primitives, but the same happens for structures. Function calls are just like further inner blocks. Note that if you put a large array in like that it can cause stack issues on some systems, since the stack size may be fixed. Anyway there are lots more details on stack vs heap (malloc) on the web.

For the kind of clever compiler memory management where it manages object/structure memory more cleverly, such as you seem to be thinking about, you'd need either reference counted objects, garbage collection or a variant. You'd really need to be using C++, Java or .NET for that to work automatically. For GP32 you could get C++ working and use the boost::shared_ptr class... Probably overkill though.

Mark
 
Last edited by a moderator:
but -

Code:
myStruct *struct;

function addStruct( myStruct *struct ){
  myStruct aStruct;
  // ...
  // Do stuff to struct
  // ...
  struct = &aStruct;
}

addStruct( struct );

// Does 'struct' now still exist? :)
 
pea posted on Oct 8 2005 at 11:05 AM said:
but -

Code:
myStruct *struct;

function addStruct( myStruct *struct ){
  myStruct aStruct;
  // ...
  // Do stuff to struct
  // ...
  struct = &aStruct;
}

addStruct( struct );

// Does 'struct' now still exist? :)

aStruct is a local thus allocated from stack when you enter the function. It's gone when you exit the function.
 
Last edited by a moderator:
You would have to allocate a new memory block from the global heap (ie malloc, or C++ new) for the struct to be valid outside the function.

Because aStruct is on the local heap it would get overwritten by the local variables in the next function to be called.

And of course! You have to remember to free them up when you're done ;)
 
Best == "how you designed your code" :)

If you need it 'right away' for a 'short tme', use it on the stack. ie: If you're just futzing with something. But if youneed a linked list or other longer term storage 'out of scope' (beyond the life of the current function/brace-pair, you need to malloc it.

jeff
 
Back
Top