Page 1 of 1

pb4.30[b4] RtlInitUnicodeString error in x64 , ok in x32

Posted: Mon Dec 01, 2008 4:26 pm
by bingo

Code: Select all

Structure UNICODE_STRING 
usLength.w 
usMaximumLength.w 
usBuffer.i
EndStructure

pu.UNICODE_STRING

Procedure Ansi2Uni(ansi.s) 
SHStrDup_(@ansi,@myuni.i)
ProcedureReturn myuni 
EndProcedure

testunistring.i = Ansi2Uni("test")

Debug testunistring ;ok

RtlInitUnicodeString_(@pu,testunistring)

Debug pu\usLength ; = 8
Debug pu\usMaximumLength ; = 10

Debug testunistring ; but 0 in x64 !?

Debug pu\usBuffer

Debug PeekS(pu\usBuffer) ; = t , but error in x64
pointer of 'testunistring' is NULL after RtlInitUnicodeString (x64) :roll:
it works in x32 ...

Posted: Mon Dec 01, 2008 4:39 pm
by freak
Just a a structure alignment problem. Use this one and it works:

Code: Select all

Structure UNICODE_STRING
usLength.w
usMaximumLength.w
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
  _alignment.l
CompilerEndIf
usBuffer.i
EndStructure

Posted: Mon Dec 01, 2008 6:25 pm
by bingo
thanks ! but where is this documented ??? :shock:

Posted: Mon Dec 01, 2008 6:49 pm
by Fred
On x64, every C structures fields of 8 bytes (pointers, quad) are padded on a 8 bytes boundary.

Posted: Mon Dec 01, 2008 9:23 pm
by Mistrel
Maybe I'm not understanding something. Wouldn't the .i in the structure compile to 8 bytes instead of 4 automatically on an x64 operating system?

Posted: Mon Dec 01, 2008 9:25 pm
by Demivec
Mistrel wrote:Maybe I'm not understanding something. Wouldn't the .i in the structure compile to 8 bytes instead of 4 automatically on an x64 operating system?
@Mistrel:

on x64 (i),(q),(*) need to align on 8 byte boundary

2(w) + 2(w) + 8(i) = (i) is not aligned on 8 byte boundary
2(w) + 2(w) +4(l) + 8(i) = (i) is aligned on 8 byte boundary

Posted: Mon Dec 01, 2008 9:26 pm
by Fred
You're right. And as the 2 fields before it are 2 words (2x2 = 4), the .i will be at the offset '4', which is not valid on x64. It needs to be on a 8 bytes boundary offset (so you add a 4 bytes padding).

If you have a structure like that:

Code: Select all

Structure x
  a.b
  b.i ; At offset 1, not good on x64
EndStructure
you will need to pad it like that:

Code: Select all

Structure x
  a.b
  pad.b[7]
  b.i ; At offset 8, ok on x64
EndStructure
Note, that it is needed only for 8 bytes field size (for 4 bytes fields size, you need to be on 4 byte boundary tough).

Posted: Mon Dec 01, 2008 11:18 pm
by Mistrel
After reading about data structure alignment I understand now how it works. On x86 processors:
Wikipedia wrote:.. the x86 architecture originally did not require aligned memory access and still works without it
I also read that it's not uncommon for the compiler to add padding automatically. Will PureBasic support something like this?

http://en.wikipedia.org/wiki/Data_structure_alignment

Posted: Mon Dec 01, 2008 11:34 pm
by Fred
I don't think we will introduce this, as automatic structure padding is somewhat tricky. You will have to know what to do anyway, so just explictely pad it and it you're done. Note: C compiler has the #pragma pack() directive which tells how to pad a structure, and when misused it leds to very hard to spot bugs.

Posted: Thu Dec 04, 2008 12:26 am
by Rescator
I've always tried to pair up words and bytes so that there are 4byte alignments out of habit really. I guess I'll have to consider pairing things up on 8bytes where possible then. (usually no harder than moving vars around in a structure and add a reserved here and there :) )