Actual Size of undeclared object?

BlitzMax Forums/BlitzMax Beginners Area/Actual Size of undeclared object?

SculptureOfSoul(Posted 2006) [#1]
[edit] Title should read "undefined object", not undeclared.

Okay, I want to utilize an object of a given type more or less as a pointer to another object of that type.

Assume Type A is 50 bytes. I assumed that if you do Temp = New Type A, that Blitzmax allocates teh 50 bytes and stores a 'pointer' in Temp. Is this correct?

Also, I assumed that if you did something like
Temp2:Type A
Temp2 = Temp

that the compiler wouldn't allocate an additional 50 bytes for Temp2 since New() is never called on it. Instead, I'm assuming that it just copies over the 'pointer' from Temp. Is this correct?

Also, if I run this code


I get some strange findings.

TBig = 12 bytes.
TBigger = 36 bytes
TBiggest = 40 bytes <---okay, so the TBig field is just a pointer.

This line, however

print sizeof( Biggest.Big )

returns 12. This is before I've even defined Biggest.Big. I'm assuming at this point it's returning the sizeof the type that Big is 'pointing to', and not the size allocated for Big itself.

I really hope that an undefined object doesn't require allocating the full sizeof the object. I plan on having a large array of these 'pointers'. The object itself might be a couple hundred bytes and I can't afford to have a 2000x2000 array of pointers that are each 200 bytes. :)


Dreamora(Posted 2006) [#2]
In that case, just declare the array to be of type :object and cast it back when you use it.
But it will none the less still need 2000x2000x200 + 2000x2000x4 bytes (first for the actual objects to fill the array and the later for the array) so you can only lose there.

ps: on the 12 bytes. I assume thats because globals need to be present anywhere and thus their RAM block is allocated even when not needed to make sure that there is place for this global when a local variable is assigned to it.


SculptureOfSoul(Posted 2006) [#3]
What has me confused is that in the example above, the field Big:TBig in Type TBiggest only adds 4 bytes to the size of the type. Before any TBiggests are instantiated it is acting as a pointer. Obviously if I create a new TBiggest the compiler is going to have to set aside the memory for "Big", but if I simply declare the variable it shouldn't need to.


Anyhow, I ran some more tests - this time with GCMemAlloced() and now I'm more confused

Print GCMemAlloced()
Local Big:TBig
Print GCMemAlloced()

Print GCMemAlloced()
Local Bigger:TBigger
Print GCMemAlloced()

Print GCMemAlloced()
Local Biggest:TBiggest
Print GCMemAlloced()


Each call to GCMemAlloced showed that 22 more bytes were alloced.


Okay, nevermind. I just did some more tests. I put a bunch of Print GCMemAlloced() all by themselves and it seems that *just the call to GCMemAlloced() (or perhaps Print)* caused the allocation of the 22 bytes.

So, in reality, no memory is set aside when a new variable is *declared*.

My next test indicated that the above sizeof() values + 8 bytes were allocated whenever the variable was actually defined. E.G:

Global Big:TBig
Big = new TBig


That allocated 42 bytes total. Subtract 22 for the GCMemAlloc() calls and we're left with 20 bytes. The original size + 8. TBigger and TBiggest, after subtracting the 22 bytes, returned 44 and 48 bytes respectively - which confirms that the size of the type + 8 bytes were allocated.

And now to test what happens when you assign an undeclared variable to an already declared variable.

Print GCMemAlloced()
Local Bigger:TBigger
Local Bigger2:TBigger        ' <---same whether commented out or not
Bigger = New TBigger
Bigger2 = Bigger                 '<---same whether commented out or not
Print GCMemAlloced()


What's strange is 66 bytes were allocated whether the lines in question above is commented out or not. Subtract the 22 bytes for the GCMemAlloced() calls and once again, 44 bytes were allocated. Sizeof(TBigger) + 8.

This also allocated only 66 bytes

Print GCMemAlloced()
Local Bigger:TBigger
Local Bigger2:TBigger
Local Bigger3:Tbigger
Local Bigger4:TBigger
Local Bigger5:TBigger

Bigger = New TBigger
Bigger2 = Bigger
Bigger3 = Bigger
Bigger4 = Bigger
Bigger5 = Bigger
Print GCMemAlloced()


So it looks like you can in fact use an undefined object as a pointer without BMax allocating memory for the full size of the type (in fact...No memory is allocated???)

Strange.


Dreamora(Posted 2006) [#4]
Locals within the main app are not handled by the GC directly and thus don't show up in GCMemAlloced.
Thats the reason method delete does not fire directly if you null-ify an app local reference and gccollect


SculptureOfSoul(Posted 2006) [#5]
If that's true, the output of this program makes no sense

Type THuge
	Field intarray:Int[10000]
	
	Method New()
	intarray = New Int[10000]
	EndMethod
EndType


Print "Before declaration: " + GCMemAlloced()
	Local Huge:THuge
Print "After declaration: " + GCMemAlloced()
	huge = New Thuge
Print "After definition: " + GCMemAlloced()


the output I got was :
Before declaration: 13428
After declaration: 13512
After definition: 93654


I'm not trying to be difficult, I just really don't understand what you're saying.