Crash on access of CString

I have a crash when reading out a CString returned from a declare call.

[code]Dim p As Ptr = … // points to a CString

// This works
Dim mb As New Xojo.Core.MemoryBlock§
Dim cs1 As CString = mb.CStringValue(0)

// This crashes
Dim cs2 As CString = p.CString(0)[/code]
The crash log shows that the C standard library function strlen crashes. If I put a break point on the last line and then investigate the memory of mb and p, they are obviously both the same as they both show the same location in memory. A string followed by 0. So why does p.CString(0) crash – the memory has not been freed or accessing p via the MemoryBlock wouldn’t work?

What happens if you change the destination string to a normal String instead of a CString?

MemoryBlock.CString and Ptr.CString have different semantics. MemoryBlock’s returns a CString created by reading from the start until the first NUL or the end of the MemoryBlock. Ptr just dereferences memory and treats it as a CString (in C terminology, it’d be analogous to starting with a char**).

Does that mean, it takes the value at the memory location it’s pointing to, and takes that as a pointer to a CString somewhere else in memory?

address value 1000 p // p As Ptr points to memory address 1012 1004 . 1008 . 1012 a // start of c string 1016 b 1020 c // end of c string 1024 \\0 // zero byte terminates the c string 1028 .

Now doing the following…

Dim cs As CString = p.CString(0)

… would – as I thought – read the c string at address 1012. As per the docs on Ptr:

[quote]You can convert the value referenced to by the pointer to a specific data type using the properties listed below.

CString(offset As Integer = 0) As CString
…[/quote]

But instead is seems to do this – if I understand Joe correctly: Go to address 1012, read the value: 97 (small “a”) and treat it as a pointer, trying to read a – non-existant – c string at address 97.

That’s what’s happening. Set it up as a Ptr to a CString and the value is read correctly

[code] dim m As new MemoryBlock(100)
dim p As Ptr = m

m.Ptr(0) = Ptr(Integer(p) + 4) //put Ptr at 0 pointing to 4

m.CString(4) = “abc” //put CString at 4

dim s As CString = p.CString(0) //read Ptr.CString from 0

break[/code]

I don’t know the reason for this or the best way to work it. If there’s no given Ptr seems you’ll have to setup and manage some intermediary

[code] dim m As new MemoryBlock(100)
dim p As Ptr = m

m.CString(16) = “abc” //CString at 16 with no Ptr to

dim intermediaryMem As new MemoryBlock(4) //setup a separate
dim intermediaryPtr As Ptr = intermediaryMem //Ptr pointing
intermediaryPtr.Ptr(0) = Ptr( Integer(p) + 16 ) //to that 16

dim s As CString = intermediaryPtr.CString(0) //read

break[/code]