The stackalloc
keyword creates a region of memory on the stack and returns a pointer to the start of that memory. Stack allocated memory is automatically removed when the scope it was created in is exited.
//Allocate 1024 bytes. This returns a pointer to the first byte.
byte* ptr = stackalloc byte[1024];
//Assign some values...
ptr[0] = 109;
ptr[1] = 13;
ptr[2] = 232;
...
Used in an unsafe context.
As with all pointers in C# there is no bounds checking on reads and assignments. Reading beyond the bounds of the allocated memory will have unpredictable results - it may access some arbitrary location within memory or it may cause an access violation exception.
//Allocate 1 byte
byte* ptr = stackalloc byte[1];
//Unpredictable results...
ptr[10] = 1;
ptr[-1] = 2;
Stack allocated memory is automatically removed when the scope it was created in is exited. This means that you should never return the memory created with stackalloc or store it beyond the lifetime of the scope.
unsafe IntPtr Leak() {
//Allocate some memory on the stack
var ptr = stackalloc byte[1024];
//Return a pointer to that memory (this exits the scope of "Leak")
return new IntPtr(ptr);
}
unsafe void Bad() {
//ptr is now an invalid pointer, using it in any way will have
//unpredictable results. This is exactly the same as accessing beyond
//the bounds of the pointer.
var ptr = Leak();
}
stackalloc
can only be used when declaring and initialising variables. The following is not valid:
byte* ptr;
...
ptr = stackalloc byte[1024];
Remarks:
stackalloc
should only be used for performance optimizations (either for computation or interop). This is due to the fact that: