In an unsafe
block, I'm trying to get a pointer to a byte
array. But I get different results depending on the declared size of the array:
unsafe {
byte[] bytes;
bytes = new byte[1];
fixed(void* pBytes = bytes)
{
((int)pBytes).Dump(); //prints e.g. 41797644
}
bytes = new byte[0];
fixed(void* pBytes = bytes)
{
((int)pBytes).Dump(); //prints 0 ?!
}
}
If I open the immediate window and type &bytes
, I get the actual addresses of the byte arrays, including the case with the empty array.
Why doesn't the fixed
unmanaged pointer work the same?
UPDATE:
Here's the same code and what I get from the immediate window:
unsafe {
byte[] bytes;
bytes = new byte[1];
fixed(void* pBytes = bytes)
{
// bytes =>
// {byte[1]}
// [0]: 0
//
// &bytes
// 0x0601c34c //the address of the variable
// bytes: 0x027dc804 //the address of the array
//
// pBytes
// 0x027dc80c // notice pBytes == (&bytes + 8)
// *pBytes: 0
}
bytes = new byte[0];
fixed(void* pBytes = bytes)
{
// bytes =>
// {byte[0]}
//
// &bytes
// 0x0601c34c //same address of the variable, ofc
// bytes: 0x02aa7ad4 //different address of (new) array
//
// pBytes
// 0x00000000 // BOINK
// *pBytes: Cannot dereference 'pBytes'.
// The pointer is not valid.
}
}
The 8-byte difference between the address of the array object (&bytes) and the array pointer is explained by the object's header.
The array representation in memory is:
type id size elem 0 elem1 ...
----|--------|--------|--------|--------|...
^ 4Bytes 4Bytes ^
| `--< pBytes
`--< &bytes
The unsafe pointer actually points to the start of, well, actual data (i.e. what would be marshalled to an unmanaged context)
Is there a way I could get, in code, the actual address of the empty array?
FWIW, I actually need that to be able to get to the array's header, to modify the array's runtime-type on the fly.