Advanced question : Structures and Memory

Everything else that doesn't fall into one of the other PB categories.
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Advanced question : Structures and Memory

Post 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 :

Code: Select all

PeekB(@packet+1)
is different than :

Code: Select all

PeekB(@packet\block1[1])
(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 ?
- Registered PB user -

Using PB 4.00
sec
Enthusiast
Enthusiast
Posts: 792
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Post 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.
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post 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.
- Registered PB user -

Using PB 4.00
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post 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?
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post 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 ?
- Registered PB user -

Using PB 4.00
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post 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?
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post 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)
- Registered PB user -

Using PB 4.00
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post 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.
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post 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 !
- Registered PB user -

Using PB 4.00
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post 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] 
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post 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 ?
- Registered PB user -

Using PB 4.00
sec
Enthusiast
Enthusiast
Posts: 792
Joined: Sat Aug 09, 2003 3:13 am
Location: 90-61-92 // EU or ASIA
Contact:

Post by sec »

newbie, Do not use * then. You can live with out * :wink:
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

The * is necessary in order to pass the structure as a paramater.

The following will give you a syntax error:

Code: Select all

Procedure myproc(var.STRUCT)
Post Reply