why is my pointer not being recognized in the struct?

Just starting out? Need help? Post your questions and find answers here.
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

why is my pointer not being recognized in the struct?

Post by jorgejones »

Code: Select all

Structure tost
  temp.l
EndStructure
Structure test
  *ptr.tost[0]
EndStructure

Debug SizeOf(test)
shouldnt this be 4 in size?, even if it begins at 1 it should still be 4 in size, because if not you have to put a placeholder value in the structure!

i am using [0] because i would like to dyn--alloc the pointers...
any way to do this??
if i set 1 and use debugger it bitches about IOB... :?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

All is well, it's by design:

Code: Select all

Structure tost
  temp.l
EndStructure

Structure test
  *ptr.tost[0]
EndStructure

*tostarray.test = AllocateMemory(SizeOf(tost)*1000)

Debug SizeOf(*tostarray)     ; the 4 you're looking for

Debug MemorySize(*tostarray) ; the room set aside for the array of tosts

*tostarray\ptr[100] = 99     ; stick a value in one of the slots

Debug *tostarray\ptr[100]    ; read it back

; note that you don't use the * character for pointers referenced in structures
; (but it goes into the original structure)
You can reallocate the memory block up and down as desired, the static array is designed to fit into any size memory allocated to it. This is the meaning of the [0] in the static array.

The test structure, consisting only of a static array of this kind, is entirely theoretical, this is why it has a size of 0. It is a template only.

This is not well documented iirc, but it's one of the coolest features of the PB language. (I impress easily, don't I?)
BERESHEIT
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

Post by jorgejones »

thank you for the explainations very useful to learn from :)
do you know if its possible to do this with more structs?

Code: Select all

Structure tast
  test.l
  bla.l
EndStructure
Structure tost
  *ptr.tast[0]
  ble.l
  blu.l
EndStructure
Structure test
  *ptr.tost[0]
  something.l
EndStructure
would it be ok to malloc a big memory area and use it to calculate the pointers of each structure array element? how could i do this properly? will it work if i also have values with custom types (other structs) ?? shouldnt i use a heap??

thanks!!

btw i didnt know about this either its not showing up in the docs i was just trying this out as an experiment
Last edited by jorgejones on Sun Nov 18, 2007 3:12 am, edited 2 times in total.
Thalius
Enthusiast
Enthusiast
Posts: 711
Joined: Thu Jul 17, 2003 4:15 pm
Contact:

Post by Thalius »

(I impress easily, don't I?)
:D I am ! This is very nifty indeed!

Thanks for a good example :)

Thalius
"In 3D there is never enough Time to do Things right,
but there's always enough Time to make them *look* right."
"psssst! i steal signatures... don't tell anyone! ;)"
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

Post by jorgejones »

:D ! anyone?
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

Post by jorgejones »

Code: Select all

Structure info
  test.l
  test2.l
EndStructure
Structure offspring
  var1.l
  var2.l
  stuff.info
EndStructure
Structure child
  *offsprings.offspring[0]
  something.l
EndStructure
Structure main
  *childs.child[0]
  something.l
EndStructure


maincount = 1
childcount = 1
offspringcount = 1

*this_main.main = AllocateMemory(SizeOf(main)*maincount)
*this_main\childs = AllocateMemory(SizeOf(child)*childcount)
*this_main\childs\offsprings = AllocateMemory(SizeOf(offspring)*offspringcount)

Debug SizeOf(offspring)

*this_main\childs[100] = 99     ; stick a value in one of the slots
Debug *this_main\childs[100]    ; read it back 

*this_main\childs[4]\something = 20
Debug *this_main\childs[4]\something

*this_main\childs[4]\offsprings[50] = 210
Debug *this_main\childs[4]\offsprings[50]

  *this_main\childs[4]\offsprings[50]\stuff\test = 210546
;  Debug *this_main\childs[4]\offsprings[50]\var1

why if i setup my counts to 1 it still works ok for everything but the last line? in all cases my last line fails but i dont know why
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

It's not just the last line, the whole thing crashes here and, to be honest, I'm not suprised. With this many pointers flying around, you're asking for trouble as you are simply not initialising the various 'levels' of pointer.

You have pointers to pointers and cases of this second level of pointer not being initialised. Also, you are simply not allocating sufficient memory anyhow.

If I were you I'd rethink what it is you are trying to do here and redesign it. Basically if you are trying to nest structures then consider using the EXTENDS keyword (have a look in the help manual under 'structure'). Also, consider removing some of these pointers and use static fields instead. Use pointers to the main structure.

Also, when using the 'trick' which comes with *childs.child[0], put this field at the end of the structure. Otherwise you will overwrite the following fields. That is, switch :

Code: Select all

Structure main 
  *childs.child[0] 
  something.l 
EndStructure 
for

Code: Select all

Structure main 
  something.l 
  *childs.child[0] 
EndStructure 
etc.

If you do not do this then you will find that after allocating enough memory for, say, 10 instances of *childs, then *childs[0] will overwrite the value of the 'something' field.
I may look like a mule, but I'm not a complete ass.
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

Post by jorgejones »

thanks i see this but how can i get it to run and why is it crashing in different places for you? :shock:

current code {almost the same one}

Code: Select all

Structure info
  test.l
  test2.l
EndStructure
Structure offspring
  var1.l
  var2.l
  stuff.info
EndStructure
Structure child
  something.l
  *offsprings.offspring[0]
EndStructure
Structure main
  something.l
  *childs.child[0]
EndStructure


DebugLevel 1
childcount = 200
offspringcount = 200

*this_main.main = AllocateMemory(SizeOf(main))
*this_main\childs = AllocateMemory(SizeOf(child)*childcount)
*this_main\childs\offsprings = AllocateMemory(SizeOf(offspring)*offspringcount)

Debug SizeOf(offspring), 2

*this_main\childs[100] = 99     ; stick a value in one of the slots
Debug *this_main\childs[100], 2    ; read it back 

*this_main\childs[4]\something = 20
Debug *this_main\childs[4]\something, 2

*this_main\childs[4]\offsprings[50] = 210
Debug *this_main\childs[4]\offsprings[50], 2


Debug *this_main\childs[4], 1
Debug *this_main\childs[4]\offsprings[50], 1
Debug *this_main\childs[4]\offsprings[50]\stuff, 1
Debug *this_main\childs[4]\offsprings[50]\stuff\test, 1

;  *this_main\childs[4]\offsprings[50]\stuff\test = 210546
;  Debug *this_main\childs[4]\offsprings[50]\var1
only reason for my mess is to learn about pointers and structs not to design anything in the very best proper way so im sorry for that :cry: i just wish it were easier for this sort of things to me it looks like the memory is being allocated now so why is it still crashing?
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Well, consider the line :

Code: Select all

*this_main\childs[100] = 99
here you are setting a pointer to a child structure but, by giving it the value of 99, you are effectively saying; 'at memory location 99 you will find a structure of type child'. Well there is nothing in your code which is actually placing anything at memory location 99!

You seem to be mixing and cofusing pointers to arrays with pointers to structures etc. and if this is set up correctly, you will need a heck of a lot more memory allocated. No, if I were you I would seriously consider abandoning this code for something far simpler. Whatever it is you are trying to achieve can undoubtedly be undertaken with far far simpler code.

Here is a working example of the kind of thing you seem to be after, but this is not good programming :

Code: Select all

Structure info 
  test.l 
  test2.l 
EndStructure 
Structure offspring 
  var1.l 
  var2.l 
  stuff.info 
EndStructure 
Structure child 
  something.l 
  *offsprings.offspring[0] 
EndStructure 
Structure main 
  something.l 
  *childs.child[0] 
EndStructure 


DebugLevel 1 
childcount = 200 
offspringcount = 5 

*this_main.main = AllocateMemory(SizeOf(long)+ childcount*SizeOf(LONG)) 
*this_main\childs[4] = AllocateMemory(SizeOf(long)+ offspringcount*SizeOf(LONG)) 
*this_main\childs[4]\offsprings = AllocateMemory(SizeOf(offspring)*offspringcount) 

a.offspring\stuff\test = 6

Debug *this_main\childs[4]
*this_main\childs[4]\offsprings[2]=@a
Debug *this_main\childs[4]\offsprings[2]\stuff\test
The tricks with *child[0] etc. is really quite an advanced feature of Purebasic and when you combine this with the multi-level pointers which you are attempting then, well this is unnecessary complication and will simply serve to confuse and massively detract from the simplicity of Purebasic and pointers.

If you make it clear what you are really after then one of us around these parts will be able to hack up a far simpler and tidier method etc. :)
I may look like a mule, but I'm not a complete ass.
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

Post by jorgejones »

thank you again it's now more clear :)
im trying to understand pointers in this case

so using *bla[0] would be like defining an array of pointers with 0 items right? (it is just a placeholder i guess)

i thought it was a pointer to an array so i could just alloc the space and place stuff inside but i was wrong

how slower is this against a linkedlist in purebasic?

are linkedlist functions real functions or some stuff is translated into operations like a macro?

ultimately i would like to dynamically create objects with their childs and childs of childs and since i do not know how to do this with linkedlists (like send a pointer to a linked list to the procedure then send back and all that) and also because someone told me theres an overhead in the procedure calls i figured it would be better if i did this on my own by allocating the memory and figuring out the pointers etcetera


my final goal is to create a life simulation it is just a logic representation and since it allows for multiple universes to be created i figured i would need it to be fully dynamic (i kinda cant do newlist blabla() because of this )

so i will have a fair amount of items in place anyway it is not scientific at all just an exercise to get better at purebasic


now that i think i get it let me see if i can enumarete what i have to do

1) allocate the space for the pointers
2) allocate the space for the actual data
3) calculate displacement and setup each pointer in the pointers pool

im in the right track or still off? :?

so i figure i would have 2 main memory addresses to cover per each element i setup by ''hand''

i want to use the final stuff as if they were allocated normally through bla[20] or whatever thats what im after here

i hope i could express it fine
thanks again
:D
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

jorgejones wrote:so using *bla[0] would be like defining an array of pointers with 0 items right? (it is just a placeholder i guess)

i thought it was a pointer to an array so i could just alloc the space and place stuff inside but i was wrong
Indeed. An array of pointers it is.

I am puzzled why you are using pointers here, i.e. why use *childs.child[0] ? Why not remove the pointers and use childs.child[0] etc. This would simplify things somewhat and, in your case, I can see no real advantage in using pointers -except to increase the amount of memory allocations you need to perform.
how slower is this against a linkedlist in purebasic?
Linked lists can be, depending on how you access individual elements, slower than using arrays etc. Of course you can use pointers to access individual elements of linked lists and so they can be very fast. However, linked lists need protecting in multi-threaded applications.
are linkedlist functions real functions or some stuff is translated into operations like a macro?
No macros involved.
ultimately i would like to dynamically create objects with their childs and childs of childs and since i do not know how to do this with linkedlists (like send a pointer to a linked list to the procedure then send back and all that) and also because someone told me theres an overhead in the procedure calls i figured it would be better if i did this on my own by allocating the memory and figuring out the pointers etcetera
There is an example in the PB help manual under 'procedures' which sends a linked list to a procedure.
now that i think i get it let me see if i can enumarete what i have to do

1) allocate the space for the pointers
2) allocate the space for the actual data
3) calculate displacement and setup each pointer in the pointers pool
You forgot 4) which is to simplify your structures massively! :wink:
im in the right track or still off? :?
In terms of making things too complex, I would say still off!

I am hesitating in creating an example for you because I am still not really sure what your requirements are in terms of the data you need to store etc?
I may look like a mule, but I'm not a complete ass.
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

Post by jorgejones »

:shock: but if i dont use * it says "Can't assign a value to a structure"

ideally i would use a linkedlist but given the amount of items i will have i think it is not a good idea

the data i will have is basic vector information {points most of it and also position acceleration structures and such}

how can i simplify the fact that theres a world with objects in it and those objects can have their own child objects which are somewhat different because they will have other properties in my simulation ?

i did think about the structure union but i do not really share that much fields in between child and offspring items only ones would be the position rotation and such

i dont know how to put it in an example i will search the net to see if i find any hierarchical thing i can use as an example

:?

about the error i have perhaps i could allocate the memory by hand too? if i get the size of the structure ?

i made a small test but it scares me because it works even if i dont try to reallocate that said why is this happening? i get no errors in my pc and the returns are always ok whats wrong? it should crash or something shouldnt it?

Code: Select all

Structure child
 something.l
 ; simplified for test
EndStructure
Structure main
  something.l
  childs.child[0]
EndStructure

Define.main world


elements = 100
ReAllocateMemory(world\childs, SizeOf(child)*elements)

world\childs[85]\something = 123456

Debug PeekL(world\childs[85])
by the way i had to try use peek function because i was getting pointer address why is this again? :? it is fishy because it does not give me an error!!
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Where is the code to AllocateMemory for this before you ReAllocate it here?

Code: Select all

ReAllocateMemory(world\childs, SizeOf(child)*elements)
World\childs doesn't contain a pointer to memory, so I don't think it should be used this way.
jorgejones
User
User
Posts: 32
Joined: Tue Mar 21, 2006 8:27 am

Post by jorgejones »

i thought it was a wrapper to heaprealloc()?

so anyway i went to msdn because a friend pointed me out about the heap functions and i got it to work with peek and poke and no * on the struct!

but i dont know if this is correct or if it works somewhere else can you please correct it if it is wrong?

Code: Select all

Define.SYSTEM_INFO lpSystemInfo
GetSystemInfo_( lpSystemInfo )

#HEAP_GENERATE_EXCEPTIONS = $00000004
#HEAP_ZERO_MEMORY = $00000008

hippie = HeapCreate_(#HEAP_GENERATE_EXCEPTIONS, lpSystemInfo\dwPageSize * 128, #Null)

If hippie
  
  Structure child
   something.l
   ; simplified for test
  EndStructure
  Structure main
    something.l
    childs.child[0]
  EndStructure
  
  child_elements = 100
  
  ptr = HeapAlloc_(hippie, #HEAP_ZERO_MEMORY, SizeOf(long)*child_elements)
  ptr2 = HeapAlloc_(hippie, #HEAP_ZERO_MEMORY, SizeOf(child)*child_elements)
  
  Define.main world
  
  PokeL( world\childs, ptr) ;world\childs = ptr
  For i=0 To child_elements
    PokeL( world\childs[i], ( ptr2+SizeOf(child) )) ;world\childs[i] = ptr2+SizeOf(child)
  Next
  
  world\childs[50]\something = 654321
  world\childs[85]\something = 123456
  
  Define.s stringy
  stringy + " " + Str(world\childs[50]\something)
  stringy + " " + Str(world\childs[85]\something)
  MessageRequester("test", stringy)
  
  HeapDestroy_(hippie)

EndIf
the heap stuff i ended up asking on an irc because i never used it :cry: it does not crash but i have my doubts if this is ok or what i still need help!

:shock:

by the way how do i make a line break in purebasic string? :? i only stared long on the memory stuff so long i have not read most of the stringy functions
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Well, the reallocate memory is having no effect and, as far as I know, you shouldn't be doing that.

I think the heart of your problem is in knowing when to allocate memory (and thus use a pointer) and when you cannot and must not do this. Of course this all arises from your wish to use something like childs.child[0] in which you are 'tricking' Purebasic into allowing a dynamic array within a structure (arrays in structures are inherently static).

Let me see if I can explain?

If you are creating a static structure as in :

Code: Select all

Structure main 
  something.l 
  childs.child[10] 
EndStructure 

world.main
then with the statement 'world.main' Purebasic has already allocated memory for the variable world (44 bytes in this case). Hence you must not attempt to allocate memory and set world equal to the resulting buffer. That is do not attempt writing 'world = AllocateMemory(...)' etc.

On the other hand, a dynamic structure such as in :

Code: Select all

Structure main 
  something.l 
  childs.child[10] 
EndStructure 

*world.main
then with the statement '*world.main' we are telling PB that *world will point to a chunk of memory representing a structure of type main. However, this pointer has not been initialised and points to nothing. This is where you might allocate some memory with :

Code: Select all

*world = AllocateMemory(SizeOf(main))
Now *world is initialised we can use it as if it was a regular structure.

The complication is when you switch childs.child[10] for childs.child[0], but I'll return to that later.

In terms of getting your code working, you need a pointer to the main structure :

Code: Select all

Structure child 
 something.l 
 ; simplified for test 
EndStructure 
Structure main 
  something.l 
  childs.child[0] 
EndStructure 

elements = 100 

*world.main = AllocateMemory(SizeOf(child)*elements+SizeOf(LONG)) ;Extra 4 bytes for 'mains' something field.

*world\childs[85]\something = 123456 

Debug PeekL(*world\childs[85])

Now, in using childs.child[0] we are stepping up a degree of complexity here. Because you are tricking PB into allowing a dynamic array in a structure (which isn't catered for because of compatability issues with the win api!) you cannot expect PB to set aside enough memory for an array whose upper bound is subject to change etc. Hence the need to dynamically allocate memory and this forces us to use at least one pointer (as above).

Compare this use of a single pointer, however, with the hundreds you had in your earlier code above!

I hope this helps.
I may look like a mule, but I'm not a complete ass.
Post Reply