stackalloc 式 (C# リファレンス)stackalloc expression (C# reference)

stackalloc 式を使用すると、スタックにメモリ ブロックを割り当てることができます。A stackalloc expression allocates a block of memory on the stack. メソッドの実行中に作成された、スタックに割り当てられたメモリ ブロックは、そのメソッドが戻るときに自動的に破棄されます。A stack allocated memory block created during the method execution is automatically discarded when that method returns. stackalloc を使用して割り当てられたメモリを明示的に開放することはできません。You cannot explicitly free the memory allocated with stackalloc. スタックに割り当てられたメモリ ブロックは、ガベージ コレクションの対象外であり、fixed ステートメントを使用してピン留めする必要はありません。A stack allocated memory block is not subject to garbage collection and doesn't have to be pinned with a fixed statement.

stackalloc 式の結果を、次のいずれかの型の変数に割り当てることができます。You can assign the result of a stackalloc expression to a variable of one of the following types:

  • C# 7.2 以降では System.Span<T> または System.ReadOnlySpan<T>。次に例を示します。Beginning with C# 7.2, System.Span<T> or System.ReadOnlySpan<T>, as the following example shows:

    int length = 3;
    Span<int> numbers = stackalloc int[length];
    for (var i = 0; i < length; i++)
    {
        numbers[i] = i;
    }
    

    スタックに割り当てられたメモリ ブロックを Span<T> 変数または ReadOnlySpan<T> 変数に割り当てるときに、unsafe コンテキストを使用する必要はありません。You don't have to use an unsafe context when you assign a stack allocated memory block to a Span<T> or ReadOnlySpan<T> variable.

    これらの型を操作するときに、次の例に示すように、条件式または代入式の中で stackalloc 式を使用できます。When you work with those types, you can use a stackalloc expression in conditional or assignment expressions, as the following example shows:

    int length = 1000;
    Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
    

    C# 8.0 以降では、次の例のように、Span<T> または ReadOnlySpan<T> の変数が許可されるところでは、他の式の中で stackalloc 式を使用できます。Beginning with C# 8.0, you can use a stackalloc expression inside other expressions whenever a Span<T> or ReadOnlySpan<T> variable is allowed, as the following example shows:

    Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
    var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6 ,8 });
    Console.WriteLine(ind);  // output: 1
    

    注意

    スタックに割り当てられたメモリを操作するときは、できるだけ Span<T> 型または ReadOnlySpan<T> 型を使用することをお勧めします。We recommend using Span<T> or ReadOnlySpan<T> types to work with stack allocated memory whenever possible.

  • ポインター型。次に例を示します。A pointer type, as the following example shows:

    unsafe
    {
        int length = 3;
        int* numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
    }
    

    前の例に示したように、ポインター型を操作するときは、unsafe コンテキストを使用する必要があります。As the preceding example shows, you must use an unsafe context when you work with pointer types.

    ポインター型の場合、ローカル変数宣言でのみ stackalloc 式を使用し、変数を初期化できます。In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable.

スタックで使用可能なメモリ容量は制限されています。The amount of memory available on the stack is limited. スタックに割り当てたメモリが多すぎると、StackOverflowException がスローされます。If you allocate too much memory on the stack, a StackOverflowException is thrown. これを回避するために、次の規則に従ってください。To avoid that, follow the rules below:

  • stackalloc を使って割り当てるメモリ容量を制限する:Limit the amount of memory you allocate with stackalloc:

    const int MaxStackLimit = 1024;
    Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[inputLength] : new byte[inputLength];
    

    スタックで使用可能なメモリ容量はコードが実行される環境によって異なるため、実際の制限値は控えめに定義する必要があります。Because the amount of memory available on the stack depends on the environment in which the code is executed, be conservative when you define the actual limit value.

  • ループ内での stackalloc の使用を避ける。Avoid using stackalloc inside loops. ループの外側でメモリ ブロックを割り当て、それをループ内で再利用してください。Allocate the memory block outside a loop and reuse it inside the loop.

新しく割り当てられたメモリの内容は未定義です。The content of the newly allocated memory is undefined. これは、使用する前に初期化する必要があります。You should initialize it before the use. たとえば、すべての項目を T 型の既定値に設定する Span<T>.Clear メソッドを使用できます。For example, you can use the Span<T>.Clear method that sets all the items to the default value of type T.

C# 7.3 以降、配列初期化子構文を使用して、新しく割り当てられたメモリの内容を定義できます。Beginning with C# 7.3, you can use array initializer syntax to define the content of the newly allocated memory. これを実行するさまざまな方法を次の例に示します。The following example demonstrates various ways to do that:

Span<int> first = stackalloc int[3] { 1, 2, 3 };
Span<int> second = stackalloc int[] { 1, 2, 3 };
ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

stackalloc T[E] では、Tアンマネージド型である必要があり、E は負でない int 値に評価される必要があります。In expression stackalloc T[E], T must be an unmanaged type and E must evaluate to a non-negative int value.

セキュリティSecurity

stackalloc を使用すると、共通言語ランタイム (CLR) のバッファー オーバーラン検出機能が自動的に有効になります。The use of stackalloc automatically enables buffer overrun detection features in the common language runtime (CLR). バッファー オーバーランが検出されると、悪意のあるコードが実行される可能性を最小限に抑えるために、プロセスはできる限り迅速に終了されます。If a buffer overrun is detected, the process is terminated as quickly as possible to minimize the chance that malicious code is executed.

C# 言語仕様C# language specification

詳細については、C# 言語仕様に関するページの「スタック割り当て」セクションと、入れ子になった stackalloc の許可に関する機能提案メモをご覧ください。For more information, see the Stack allocation section of the C# language specification and the Permit stackalloc in nested contexts feature proposal note.

関連項目See also