Partage via


Expression stackalloc (référence C#)

Une expression stackalloc alloue un bloc de mémoire dans la pile. Un bloc de mémoire alloué dans la pile pendant l’exécution de la méthode est automatiquement supprimé lorsque cette méthode retourne un résultat. Vous ne pouvez pas libérer explicitement la mémoire allouée avec stackalloc. Un bloc de mémoire alloué dans la pile n’est pas soumis au nettoyage de la mémoire et ne doit pas être épinglé avec une instruction fixed.

La documentation de référence du langage C# décrit la version la plus récente du langage C#. Il contient également la documentation initiale des fonctionnalités dans les préversions publiques pour la prochaine version du langage.

La documentation identifie toute fonctionnalité introduite en premier dans les trois dernières versions de la langue ou dans les préversions publiques actuelles.

Conseil / Astuce

Pour savoir quand une fonctionnalité a été introduite en C#, consultez l’article sur l’historique des versions du langage C#.

Vous pouvez attribuer le résultat d’une expression stackalloc à une variable d’un des types suivants :

  • System.Span<T> ou System.ReadOnlySpan<T>, comme le montre l’exemple suivant :

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

    Vous n’avez pas besoin d’utiliser un contexte non sécurisé lorsque vous affectez un bloc de mémoire alloué à une pile à une Span<T> ou ReadOnlySpan<T> une variable.

    Lorsque vous travaillez avec ces types, vous pouvez utiliser une expression stackalloc les expressions conditionnelles ou d’affectation, comme le montre l’exemple suivant :

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

    Vous pouvez utiliser une expression stackalloc ou une expression de collection dans d’autres expressions chaque fois qu’une variable Span<T> ou ReadOnlySpan<T> est autorisée, comme le montre l’exemple suivant :

    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
    

    Remarque

    Utilisez ou ReadOnlySpan<T> types Span<T> pour utiliser la mémoire allouée à la pile dans la mesure du possible.

  • Un type pointeur, comme illustré dans l’exemple suivant :

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

    Comme le montre l’exemple précédent, vous devez utiliser un contexte unsafe lorsque vous travaillez avec des types pointeurs.

    Pour les types de pointeurs, vous pouvez utiliser une stackalloc expression uniquement dans une déclaration de variable locale pour initialiser la variable.

La quantité de mémoire disponible dans la pile est limitée. Si vous allouez trop de mémoire dans la pile, une StackOverflowException est levée. Pour éviter cette exception, suivez ces règles :

  • Limitez la quantité de mémoire que vous allouez avec stackalloc. Par exemple, si la taille de mémoire tampon prévue est inférieure à une certaine limite, vous allouez la mémoire dans la pile ; sinon, utilisez un tableau de la longueur requise, comme le montre le code suivant :

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

    Remarque

    Étant donné que la quantité de mémoire disponible sur la pile dépend de l’environnement dans lequel le code s’exécute, soyez prudent lorsque vous définissez la valeur limite réelle.

  • Évitez d’utiliser des boucles internes stackalloc. Allouez le bloc de mémoire en dehors d’une boucle et réutilisez-le à l’intérieur de la boucle.

Le contenu de la mémoire nouvellement allouée n’est pas défini. Vous devez l’initialiser, soit avec un stackalloc initialiseur, soit une méthode comme Span<T>.Clear avant son utilisation.

Important

L’initialisation de la mémoire allouée par stackalloc est une différence importante par rapport à l’opérateur new . La mémoire allouée à l’aide de l’opérateur new est initialisée au modèle 0 bits.

Vous pouvez utiliser la syntaxe d’initialiseur de tableau pour définir le contenu de la mémoire nouvellement allouée. L’exemple suivant illustre différentes manières de le faire :

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];

Dans l’expression stackalloc T[E], T doit être un type non managé et E doit être évalué à une valeur int non négative. Lorsque vous utilisez la syntaxe d’expression de collection pour initialiser l’étendue, le compilateur peut utiliser le stockage alloué à la pile pour une étendue s’il ne respecte pas la sécurité ref.

Sécurité

L’utilisation stackalloc active automatiquement les fonctionnalités de détection de dépassement de mémoire tampon dans le Common Language Runtime (CLR). Si le runtime détecte un dépassement de mémoire tampon, il met fin au processus le plus rapidement possible pour réduire le risque que le code malveillant s’exécute.

spécification du langage C#

Pour plus d’informations, consultez la section Allocation de pile de la spécification du langage C#.

Voir aussi