ブロックで、配列unsafe
へのポインターを取得しようとしています。byte
しかし、配列の宣言されたサイズに応じて、異なる結果が得られます。
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 ?!
}
}
イミディエイト ウィンドウを開いて と入力&bytes
すると、空の配列の場合も含めて、バイト配列の実際のアドレスが取得されます。
fixed
アンマネージ ポインターが同じように機能しないのはなぜですか?
アップデート:
同じコードと、イミディエイト ウィンドウから取得したものを次に示します。
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.
}
}
配列オブジェクトのアドレス (&bytes) と配列ポインターの 8 バイトの違いは、オブジェクトのヘッダーによって説明されます。
メモリ内の配列表現は次のとおりです。
type id size elem 0 elem1 ...
----|--------|--------|--------|--------|...
^ 4Bytes 4Bytes ^
| `--< pBytes
`--< &bytes
unsafe ポインターは実際には、実際のデータ (つまり、アンマネージ コンテキストにマーシャリングされるもの)の先頭を指しています。
空の配列の実際のアドレスをコードで取得する方法はありますか?
FWIW、実際には、配列のヘッダーにアクセスして、配列のランタイムタイプをその場で変更できるようにする必要があります。