Page 1 of 1
Advanced question : Structures and Memory
Posted: Wed Aug 18, 2004 3:13 am
by newbie
Hi,
I am doing my own protocol to send over a network, and I use a structure such as :
Code: Select all
packet.mystruct
Structure mystruct
block1.b[256]
block2.b[256]
block3.b[256]
. ..
endStructure
When I move blocks of memory (of the right size) into the structure and that I send it, there is no problem at all on the other side to read the data,
when I request the byte of packet\block1[56] I have the packet\block1[56] which was sent.
So what's the problem ?
When I dump the structure memory into a text file for instance, I see that the total bytes is indeed the total structure size (let's say 768 bytes) but that the first 256 bytes are starting after 76 random data bytes.
I mean that the packet is as follow :
76 bytes of random data (don't know what it is)
256 bytes
256 bytes
256 bytes (-76 so)
I mean that :
is different than :
(or PeekB(@packet\block1[0]))
What are these first weird bytes ? is it a kind of structure declaration ?
To say how many part there is, how many long ?
Or is there definitly a bug in my prog ? (either for the output or for making the packet).
What is weird is that when I access the struture normally (@packet\block1[1]) there is no gap of 76 bytes, each byte is where it should be, that's why I am thinking to a structure declaration.
any idea ?
Posted: Wed Aug 18, 2004 5:31 am
by sec
Code: Select all
Structure mystruct
block1.b[256]
block2.b[256]
block3.b[256]
EndStructure
packet.mystruct
packet\block1[1] = 1
Debug @packet
Debug @packet\block1[1]
Debug PeekB(@packet + 1)
Debug PeekB(@packet\block1[1])
run well at here.
from manual:
Please note, that in structures a static array[] doesn't behave like the normal BASIC array (defined using Dim) to be conform to the C/C++ structure format (to allow direct API structure porting). This means that a[2] will allocate an array from 0 to 1 where Dim a(2) will allocate an array from 0 to 2.
Posted: Wed Aug 18, 2004 12:00 pm
by newbie
Thanks for the precision Sec
So it must be something wrong on my side, I will debug before sending the packet after each time I add data to the structure and I will found the pb I hope.
Posted: Wed Aug 18, 2004 12:43 pm
by GedB
newbie,
Sec's code works okay for me too.
Can you write some minimum code to replicate the error that could be posted to the forum?
Posted: Wed Aug 18, 2004 1:37 pm
by newbie
Hi,
I just found my mistake, I was using a procedure like :
Code: Select all
Procedure Display_Memory(*packet.mystruct, start.l, endtext.l)
Debug " "
Debug " ----- "
Debug " "
For i = start To endtext - 1
Debug Chr(PeekB(@*packet+i) & $FF)
Next i
EndProcedure
notice the @*packet, instead of :
Code: Select all
; right code
Debug Chr(PeekB(*packet+i) & $FF)
My procedure is more complex but the first part of the code was displaying random memory content.
Sorry for the false alarm, next time I'll check more my code.
Anyway I'm happy that my protocol isn't flawed, ouf...
(i'll probably post this Memory_Dump procedure which display a memory area like tcpdump on Linux)
EDIT : when do I have to use @*var instead of *var ?
I mean I have procedures in my progs such as :
myproc(*var.struct)
CopyMemory...... @*var\block1
If I just put *var it crash (windows memory error message), why ?
This proc is started as a thread, is it linked ?
Posted: Wed Aug 18, 2004 5:58 pm
by GedB
Newbie there are two symbols here:
@ provides the address of a variable or function. It is a modifier that is applied to existing variables.
Given Var.l and @Var, var is a long variable and @Var is the address of that variable.
* signifies that a variable is a pointer. It is a naming convention that tells the compiler to treat the pointer differently.
Given Var.MyStruct and *Var.MyStruct then these are two entirely separate variables. Var.MyStruct is a variable of type MyStruct. *Var.MyStruct is a long variable that points to a variable of type MyStruct.
@*Var.MyStruct will give you a pointer to that pointer.
Your copy memories sound a bit suspect. You may want to take a closer look.
Can you put an example together?
Posted: Wed Aug 18, 2004 7:02 pm
by newbie
I've just understood the whole thing
About the Copymemory, you don't have the choice, when you pass a structure to a procedure, you have to give his address.
Below a code example :
Code: Select all
Structure STRUCT
block1.b[16]
block2.b[16]
EndStructure
Procedure myproc(*var.STRUCT)
;not correct, do not show the real content
Debug *var\block1
Debug *var\block1[0]
;CRASH
;Debug "block1 = " + PeekS(*var\block1[0])
;do not crash
Debug "block1 = " + PeekS(@*var\block1[0])
Debug "block2 = " + PeekS(@*var\block2[0])
;CRASH
;CopyMemory(*var\block2[0], *var\block1[0], Len(PeekS(*var\block2[0])))
;do not crash
CopyMemory(@*var\block2[0], @*var\block1[0], Len(PeekS(@*var\block2[0])))
Debug "block1 = " + PeekS(@*var\block1[0])
Debug "block2 = " + PeekS(@*var\block2[0])
EndProcedure
myvar.STRUCT
PokeS(@myvar\block1[0], "example")
PokeS(@myvar\block2[0], "of purebasic")
;calling MyProc
myproc(@myvar)
Posted: Wed Aug 18, 2004 7:48 pm
by GedB
What is happending here is that you are dereferencing the pointer.
*Var contains the pointer to the MyStruct.
*Var\block1[0] dereferences the pointer, because you are accessing one of its elements. It returns the content of that element, not it's address. To get the address you have to add an @.
Code: Select all
Structure STRUCT
block1.b[16]
block2.b[16]
EndStructure
Procedure myproc(*var.STRUCT)
;The pointer to the block
Debug *var
;A pointer to the pointer
Debug @*var
;The contents of the first element
Debug Chr(*var\block1[0])
;The pointer to the blocks first element
Debug @*var\block1[0]
EndProcedure
myvar.STRUCT
PokeS(@myvar\block1[0], "example")
PokeS(@myvar\block2[0], "of purebasic")
;calling MyProc
myproc(@myvar)
Hope this makes sense.
Posted: Wed Aug 18, 2004 8:03 pm
by newbie
Thanks for you explanations, and I like you small piece of code, I should add other lines to see by myself if there is not other "surprises"
I didn't know what was pointer dereferencing, and didn't know that I was doing that (didn't know that it was possible !).
I think they should add it to the help file, it has confused me since a long time !
At start I read that I must pass the address of the structure, so did I.
Then I read *var is a pointer inside the called procedure, that makes sense since you passed the address and not the content.
But the help does not mention that when you pass the content of the pointer to a function that requires an address as argument that it will crash because the pointer is not anymore a pointer but a variable.
Something to add I think :roll:
EDIT :
These 3 lines explains all to me :
Code: Select all
;The contents of the first element
Debug Chr(*var\block1[0])
;The contents of the first element
Debug PeekS(@*var\block1[0], 1)
;the content of the first block
Debug PeekS(*var)
That wasn't so obvious !
Posted: Thu Aug 19, 2004 12:18 am
by GedB
It took me a while to get round this as well.
I wonder if this would be a clearer format:
Code: Select all
;The pointer to the blocks first element
Debug *var\@block1[0]
Posted: Thu Aug 19, 2004 12:31 am
by newbie
On this last line I get a syntax error "structure field missing".
May be did you point this one just for the idea ?
Posted: Thu Aug 19, 2004 2:28 am
by sec
newbie, Do not use * then. You can live with out *

Posted: Thu Aug 19, 2004 9:20 am
by GedB
The * is necessary in order to pass the structure as a paramater.
The following will give you a syntax error: