ekspresi stackalloc (referensi C#)

Ekspresi stackalloc mengalokasikan blok memori pada tumpukan. Blok memori yang dialokasikan tumpukan yang dibuat selama eksekusi metode secara otomatis dibuang ketika metode tersebut kembali. Anda tidak dapat secara eksplisit membebaskan memori yang dialokasikan dengan stackalloc. Blok memori yang dialokasikan tumpukan tidak tunduk pada pengumpulan sampah dan tidak harus disematkan dengan fixed pernyataan.

Anda bisa menetapkan hasil stackalloc ekspresi ke variabel dari salah satu jenis berikut:

  • System.Span<T> atau System.ReadOnlySpan<T>, seperti yang ditunjukkan contoh berikut:

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

    Anda tidak perlu menggunakan konteks yang tidak aman saat menetapkan blok memori yang dialokasikan pada tumpukan ke variabel Span<T> atau ReadOnlySpan<T>.

    Saat bekerja dengan jenis tersebut, Anda bisa menggunakan stackalloc ekspresi dalam ekspresi kondisi atau penugasan, seperti yang ditunjukkan contoh berikut:

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

    Anda dapat menggunakan stackalloc ekspresi atau ekspresi koleksi di dalam ekspresi lain setiap kali Span<T> variabel atau ReadOnlySpan<T> diizinkan, seperti yang ditunjukkan contoh berikut:

    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<int> numbers2 = [1, 2, 3, 4, 5, 6];
    var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);
    Console.WriteLine(ind2);  // output: 1
    

    Catatan

    Sebaiknya gunakan jenis Span<T> atau ReadOnlySpan<T> untuk bekerja dengan tumpukan memori yang dialokasikan jika memungkinkan.

  • Jenis penunjuk, seperti yang ditunjukkan contoh berikut:

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

    Seperti yang ditunjukkan contoh sebelumnya, Anda harus menggunakan unsafe konteks saat bekerja dengan jenis penunjuk.

    Dalam kasus jenis penunjuk, Anda hanya dapat menggunakan stackalloc ekspresi dalam deklarasi variabel lokal untuk menginisialisasi variabel.

Jumlah memori yang tersedia pada tumpukan terbatas. Jika Anda mengalokasikan terlalu banyak memori pada tumpukan, akan StackOverflowException dilemparkan. Untuk menghindari hal tersebut, ikuti aturan di bawah ini:

  • Batasi jumlah memori yang Anda alokasikan dengan stackalloc. Misalnya, jika ukuran buffer yang dimaksudkan di bawah batas tertentu, Anda mengalokasikan memori pada tumpukan; jika tidak, gunakan array dengan panjang yang diperlukan, seperti yang ditunjukkan oleh kode berikut:

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

    Catatan

    Karena jumlah memori yang tersedia pada tumpukan tergantung pada lingkungan tempat kode dijalankan, bersikaplah konservatif saat Anda menentukan nilai batas aktual.

  • Hindari menggunakan stackalloc perulangan dalam. Alokasikan blok memori di luar perulangan dan gunakan kembali di dalam perulangan.

Konten memori yang baru dialokasikan tidak terdefinisi. Anda harus menginisialisasinya sebelum penggunaan. Misalnya, Anda dapat menggunakan Span<T>.Clear metode yang mengatur semua item ke nilai default jenis T.

Anda dapat menggunakan sintaksis penginisialisasi array untuk menentukan konten memori yang baru dialokasikan. Contoh berikut menunjukkan berbagai cara untuk melakukannya:

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

// Using collection expressions:
Span<int> fourth = [1, 2, 3];
ReadOnlySpan<int> fifth = [1, 2, 3];

Dalam ekspresi stackalloc T[E], T harus merupakan jenis yang tidak dikelola dan E harus mengevaluasi ke nilai int non-negatif. Saat Anda menggunakan sintaks ekspresi koleksi untuk menginisialisasi rentang, pengkompilasi dapat menggunakan penyimpanan tumpukan yang dialokasikan untuk rentang jika tidak akan melanggar keamanan ref.

Keamanan

Penggunaan stackalloc secara otomatis memungkinkan fitur deteksi overrun buffer dalam runtime bahasa umum (CLR). Jika overrun buffer terdeteksi, proses dihentikan secepat mungkin untuk meminimalkan kemungkinan kode berbahaya dijalankan.

Spesifikasi bahasa C#

Untuk informasi selengkapnya, lihat bagian Alokasi tumpukanspesifikasi bahasa C# dan catatan proposal fitur Izin stackalloc dalam konteks berlapis.

Lihat juga