stackalloc
è una parola chiave in C# che permette di allocare un blocco di memoria sullo Stack, invece che sull’Heap. Poiché la memoria allocata sullo stack viene automaticamente rilasciata quando il metodo corrente termina, l’utilizzo di stackalloc
può ridurre la pressione sul garbage collector e migliorare le prestazioni dell’applicazione.
Quando utilizzarlo
L’utilizzo principale di stackalloc
è come alternativa all'allocazione di memoria sull'heap per gli array, specialmente per array di piccole dimensioni e quando si cerca di ottenere un miglioramento delle prestazioni.
Ecco 10 casi d’uso in cui stackalloc
può essere utile:
- Allocazione di array temporanei: Se hai bisogno di un array temporaneo per eseguire un’operazione specifica e la dimensione dell’array è piccola,
stackalloc
può essere utilizzato per creare l’array sullo stack, migliorando le prestazioni. - Interoperabilità con codice non gestito:
stackalloc
può essere utilizzato per allocare rapidamente memoria sullo stack quando si lavora con codice non gestito (ad esempio, chiamate a funzioni di librerie native), per passare dati tra codice gestito e non gestito. - Strutture dati temporanee:
stackalloc
può essere utile per creare strutture dati temporanee per eseguire un’operazione specifica, senza dover allocare memoria sull’heap. - Buffer per I/O:
stackalloc
può essere utilizzato per creare rapidamente buffer temporanei per eseguire operazioni di input/output (ad esempio, leggere o scrivere dati da file o socket). - Calcolo di hash: Durante il calcolo di hash su una sequenza di dati,
stackalloc
può essere utilizzato per allocare un buffer temporaneo sullo stack per memorizzare l’hash calcolato. - Codifica e decodifica:
stackalloc
può essere utilizzato per allocare buffer temporanei per eseguire operazioni di codifica e decodifica (ad esempio, conversione tra codifiche di caratteri, codifica/decodifica base64, ecc.). - Compressione e decompressione: Quando si lavora con algoritmi di compressione o decompressione,
stackalloc
può essere utilizzato per allocare buffer temporanei per gestire i dati compressi/decompressi. - Crittografia:
stackalloc
può essere utilizzato per allocare buffer temporanei per eseguire operazioni di crittografia e decrittografia, ad esempio quando si lavora con algoritmi simmetrici o asimmetrici. - Elaborazione di immagini: Durante l’elaborazione di immagini,
stackalloc
può essere utilizzato per allocare buffer temporanei per contenere i dati dell’immagine o per eseguire operazioni come la convoluzione o il filtraggio. - Gestione delle matrici: Quando si lavora con matrici,
stackalloc
può essere utilizzato per allocare matrici temporanee per operazioni come la trasposizione, la moltiplicazione o la decomposizione.
Come utilizzarlo
Quando si utilizza stackalloc
, si alloca un blocco di memoria sullo stack che può essere utilizzato per memorizzare un insieme di elementi di tipo valore. Tuttavia, stackalloc
restituisce un puntatore a tale blocco di memoria, che può comportare rischi in termini di sicurezza e stabilità se non viene gestito correttamente.
Posso utilizzare la classe Span<T>
(vedi Span e ReadOnlySpan; Span<T>
è un tipo di struttura che rappresenta una vista contigua di memoria di una collezione di elementi di tipo T
) per creare una vista sicura e gestita del blocco di memoria allocato sullo stack.
Stackalloc
può essere usato per inizializzare un oggetto Span<T>
che rappresenta il blocco di memoria allocato.
Limitazioni
Le limitazioni di stackalloc
sono principalmente dovute alla natura dello stack e alle sue implicazioni per la gestione della memoria. Di seguito sono elencate alcune delle principali limitazioni associate all’uso di stackalloc
in C#:
- Dimensione limitata dello stack: Lo stack ha generalmente una dimensione molto più piccola rispetto all’heap. Di conseguenza, l’allocazione di grandi quantità di memoria sullo stack può causare un’eccezione
StackOverflowException
. Pertanto, è importante utilizzarestackalloc
solo per blocchi di memoria di dimensioni ridotte e per brevi periodi. - Compatibilità solo con tipi di valore senza riferimenti:
stackalloc
può essere utilizzato solo con tipi di valore che non contengono riferimenti, come i tipi primitivi (ad es.int
,float
,double
, ecc.) e lestruct
che contengono solo tipi di valore. Se si tenta di utilizzarestackalloc
con un tipo di valore che contiene riferimenti, verrà generato un errore di compilazione. - Vita breve degli oggetti allocati: Gli oggetti allocati con
stackalloc
hanno una durata limitata al metodo corrente. Non è possibile restituire un riferimento a un oggetto allocato sullo stack al chiamante del metodo, in quanto la memoria verrà automaticamente rilasciata alla fine del metodo. Per ovviare a questo problema, è possibile utilizzareSpan<T>
o copiare il contenuto dell’oggetto allocato sullo stack in un oggetto allocato sull’heap.
Esempio
Nell’esempio seguente, mettiamo a confronto due versioni di un metodo CalculateSumOfSquares
che calcola la somma dei quadrati di un intervallo di numeri interi. Nel primo esempio, utilizziamo stackalloc
per allocare l’array temporaneo sullo stack. Nel secondo esempio, invece, allocchiamo l’array sull’heap.