56 バイトのオーバーヘッドが必要です。実際には、2,147,483,649-1から最大サイズの 56 を引いた値です。そのため、マイナス57 は機能し、マイナス56 は機能しません。
ジョン・スキートがここで言っているように:
ただし、実際には、このような巨大な配列をサポートする実装はないと思います。CLR には 2GB に少し足りないオブジェクトごとの制限があるため、バイト配列でさえ実際には 2147483648 要素を持つことはできません。少し実験したところ、私のボックスでは、作成できる最大の配列は new byte[2147483591] であることがわかりました。(これは 64 ビットの .NET CLR 上にあります。私がインストールした Mono のバージョンは、その上にチョークをインストールしています。)
同じ主題に関するこのInformIT の記事も参照してください。最大サイズとオーバーヘッドを示す次のコードを提供します。
class Program
{
static void Main(string[] args)
{
AllocateMaxSize<byte>();
AllocateMaxSize<short>();
AllocateMaxSize<int>();
AllocateMaxSize<long>();
AllocateMaxSize<object>();
}
const long twogigLimit = ((long)2 * 1024 * 1024 * 1024) - 1;
static void AllocateMaxSize<T>()
{
int twogig = (int)twogigLimit;
int num;
Type tt = typeof(T);
if (tt.IsValueType)
{
num = twogig / Marshal.SizeOf(typeof(T));
}
else
{
num = twogig / IntPtr.Size;
}
T[] buff;
bool success = false;
do
{
try
{
buff = new T[num];
success = true;
}
catch (OutOfMemoryException)
{
--num;
}
} while (!success);
Console.WriteLine("Maximum size of {0}[] is {1:N0} items.", typeof(T).ToString(), num);
}
}
最後に、この記事には次のように書かれています。
計算すると、配列を割り当てるためのオーバーヘッドが 56 バイトであることがわかります。オブジェクトのサイズが原因で、最後にいくつかのバイトが残っています。たとえば、268,435,448 個の 64 ビット数値は 2,147,483,584 バイトを占有します。56 バイトの配列オーバーヘッドを追加すると、2,147,483,640 になり、2 ギガバイトに 7 バイト不足することになります。
編集:
しかし、待ってください。
Jon Skeet を見回して話していると、彼はOf memory and stringsに書いた記事を教えてくれました。その記事で、彼はサイズの表を提供しています。
Type x86 size x64 size
object 12 24
object[] 16 + length * 4 32 + length * 8
int[] 12 + length * 4 28 + length * 4
byte[] 12 + length 24 + length
string 14 + length * 2 26 + length * 2
スキート氏は次のように続けます。
上記の数値を見て、オブジェクトの「オーバーヘッド」が x86 では 12 バイト、x64 では 24 バイトであると考えるのは許されるかもしれませんが、それは正しくありません。
この:
x86 ではオブジェクトごとに 8 バイト、x64 ではオブジェクトごとに 16 バイトの「ベース」オーバーヘッドがあります... x86 で「実際の」データの Int32 を格納でき、オブジェクト サイズは 12 のままであり、同様に格納できます。 x64 の実データの 2 つの Int32 であり、x64 のオブジェクトがまだあります。
それぞれ 12 バイトと 24 バイトの「最小」サイズがあります。つまり、オーバーヘッドだけの型を持つことはできません。「Empty」クラスが Object のインスタンスを作成するのと同じサイズを占めることに注意してください... CLR はデータのないオブジェクトを操作することを好まないため、事実上、いくらかの余裕があります。(ローカル変数であっても、フィールドのない構造体もスペースを占有することに注意してください。)
x86 オブジェクトは 4 バイト境界までパディングされます。x64 では 8 バイトです (以前と同様)。
そして最後に、Jon Skeet は別の質問で私が彼に尋ねた質問に答えました (私が彼に見せたInformIT の記事への回答として):
あなたが参照している記事は、制限からオーバーヘッドを推測しているように見えますが、これは
ばかげたIMO です。
あなたの質問に答えるために、実際のオーバーヘッドは24 バイトで、32 バイトの空き容量があります。