stackalloc 식(C# 참조)
stackalloc
식은 스택에 메모리 블록을 할당합니다. 메서드 실행 중에 생성된 스택 할당 메모리 블록은 해당 메서드가 반환될 때 자동으로 삭제됩니다. stackalloc
을 사용하여 할당된 메모리를 명시적으로 해제할 수 없습니다. 스택 할당 메모리 블록에는 가비지 수집이 적용되지 않으며, fixed
문을 사용해서 고정하지 않아도 됩니다.
stackalloc
식의 결과를 다음 형식 중 하나의 변수에 할당할 수 있습니다.
다음 예제와 같이 System.Span<T> 또는 System.ReadOnlySpan<T>가 표시됩니다.
int length = 3; Span<int> numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; }
Span<T> 또는 ReadOnlySpan<T> 변수에 스택 할당 메모리 블록을 할당할 때 unsafe 컨텍스트를 사용하지 않아도 됩니다.
이러한 형식으로 작업하는 경우 다음 예제와 같이 조건식 또는 대입식에
stackalloc
식을 사용할 수 있습니다.int length = 1000; Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
다음 예제와 같이 Span<T> 또는 ReadOnlySpan<T> 변수가 허용되는 경우 다른 식 내부에서
stackalloc
식 또는 컬렉션 식을 사용할 수 있습니다.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
참고 항목
스택 할당 메모리로 작업할 때는 가능한 한, Span<T> 또는 ReadOnlySpan<T> 형식을 사용하는 것이 좋습니다.
포인터 형식(다음 예제 참조)
unsafe { int length = 3; int* numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; } }
포인터 형식으로 작업할 때는 위 예제와 같이
unsafe
컨텍스트를 사용해야 합니다.포인터 형식의 경우 지역 변수 선언에서만
stackalloc
식을 사용하여 변수를 초기화할 수 있습니다.
스택에서 사용 가능한 메모리 양이 제한됩니다. 스택에 너무 많은 메모리를 할당하는 경우 StackOverflowException이 throw됩니다. 이를 방지하려면 다음 규칙을 따르세요.
stackalloc
을 사용하여 할당하는 메모리의 양을 제한합니다. 예를 들어, 의도한 버퍼 크기가 특정 한도 미만이면 스택에 메모리를 할당합니다. 그렇지 않으면 다음 코드와 같이 필요한 길이의 배열을 사용합니다.const int MaxStackLimit = 1024; Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[MaxStackLimit] : new byte[inputLength];
참고
스택에서 사용 가능한 메모리 양은 코드를 실행하는 환경에 따라 달라지므로 실제 제한 값을 정의할 때는 신중해야 합니다.
루프 내부에서
stackalloc
을 사용하지 마세요. 루프 외부에서 메모리 블록을 할당하고 루프 내부에서 다시 사용합니다.
새로 할당된 메모리의 콘텐츠는 정의되지 않습니다. 사용하기 전에 초기화해야 합니다. 예를 들어 모든 항목을 T
형식의 기본값으로 설정하는 Span<T>.Clear 메서드를 사용할 수 있습니다.
배열 이니셜라이저 구문을 사용하여 새로 할당된 메모리의 콘텐츠를 정의할 수 있습니다. 다음 예제에서는 이 작업을 수행하는 다양한 방법을 보여 줍니다.
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];
식 stackalloc T[E]
에서 T
는 관리되지 않는 형식이어야 하며 E
는 음수가 아닌 int 값으로 계산되어야 합니다. 컬렉션 식 구문을 사용하여 범위를 초기화할 때 컴파일러는 ref 안전을 위반하지 않는 경우 범위에 대해 스택 할당 스토리지를 사용할 수 있습니다.
보안
stackalloc
를 사용하면 CLR(공용 언어 런타임)에서 버퍼 오버런 검색 기능이 자동으로 사용됩니다. 버퍼 오버런이 검색되면 악성 코드가 실행될 가능성을 최소화하기 위해 최대한 빨리 프로세스가 종료됩니다.
C# 언어 사양
자세한 내용은 C# 언어 사양의 스택 할당 섹션과 중첩 컨텍스트 기능 제안 노트의 stackalloc
허용을 참조하세요.
참고 항목
.NET