int* p = stackalloc int[10];
Span<int> buffer = stackalloc int[10];
처음 보면 “이게 대체 뭐지?” 싶은데, 한 번 잡고 가면
스택/힙 구조, 고성능 코드 이해에 꽤 도움이 되는 키워드다.
stackalloc 한 줄 정의
stackalloc은 “힙(heap)이 아니라 스택(stack)에 작은 배열(버퍼)을 직접 만들어 쓰자”는 키워드다.
보통 우리는 이렇게 배열을 만든다.
int[] arr = new int[10];
반면 stackalloc을 쓰면:
int* p = stackalloc int[10]; // 스택에 int 10개짜리 버퍼 생성
int 10개짜리 버퍼가 만들어지고즉, 한 마디로 요약하면:
“잠깐 쓸 작은 배열을 힙 대신 스택에 올려서 빠르게 쓰고 한 번에 정리하자”
일반적인 업무 코드에서는 stackalloc을 자주 쓰지 않는다.
하지만 다음과 같은 상황에서는 꽤 유용하다.
new byte[1024]를 만들어서 쓰면:
stackalloc으로 스택에 버퍼를 만들면:
byte*, int* 같은 포인터 버퍼를 stackalloc으로 만들고 바로 네이티브 함수에 넘길 수 있다.Span<T>와 함께 쓰는 고성능 문자열/버퍼 처리Span<byte> buffer = stackalloc byte[256];정리하면:
“작고, 일시적이고, 성능이 중요한 버퍼”가 필요한 경우 → stackalloc 후보
가장 기본 형태는 C 스타일 포인터와 함께 쓰는 것이다.
unsafe
{
int* p = stackalloc int[5]; // 스택에 int 5개짜리 버퍼 생성
for (int i = 0; i < 5; i++)
{
p[i] = i * 10;
}
for (int i = 0; i < 5; i++)
{
Console.WriteLine(p[i]);
}
}
unsafe 문맥이 필요하다.int*, byte* 같은 포인터 연산을 직접 쓸 수 있다.Span<T> 기반 (요즘 추천 스타일)
C# 7.2+에서는 Span<T>와 함께 쓰면 unsafe 없이도 stackalloc을 사용할 수 있다.
using System;
class Program
{
static void Main()
{
Span<int> buffer = stackalloc int[5]; // 스택에 int 5개
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = i * 10;
}
foreach (var x in buffer)
{
Console.WriteLine(x);
}
}
}
Span<T>는 “연속된 메모리 블록”을 안전하게 다루기 위한 타입이다.stackalloc으로 만든 버퍼를 Span으로 감싸면:
“스택에 만든다”는 말은 단순히 위치만 다른 게 아니라, 수명, 속도, 크기 제한에서 차이가 난다는 뜻이다.
예를 들어, 이런 코드는 위험하다.
unsafe int* MakeBuffer()
{
int* p = stackalloc int[10];
return p; // ❌ 함수가 끝나면 p가 가리키는 메모리는 이미 사라진 상태
}
stackalloc byte[256] 정도는 괜찮지만,
stackalloc byte[1024 * 1024] 이런 건 스택 오버플로우 위험이 있다.new 배열과 비교 – heap vs stack같은 int 100개라도, 다음 둘은 완전히 다르게 동작한다.
// 1) 힙에 생성
int[] arr = new int[100];
// 2) 스택에 생성
Span<int> buf = stackalloc int[100];
| 구분 | new int[100] (Heap) |
stackalloc int[100] (Stack) |
|---|---|---|
| 메모리 위치 | 힙(Heap) | 스택(Stack) |
| 수명 | 변수를 더 이상 참조하지 않을 때, GC가 수거 | 현재 메서드/블록 끝날 때 자동 소멸 |
| 할당 비용 | 상대적으로 비쌈 (힙 관리 + GC 부담) | 매우 빠름 (스택 포인터 이동 수준) |
| 크기 제한 | 사실상 메모리 한도까지 가능 | 크게 잡으면 스택 오버플로우 위험 |
| 사용 난이도 | 가장 일반적인 방식, 안전 | 잘못 쓰면 위험 → 주의 필요 |
stackalloc으로 만들면 스택 오버플로우 가능성이 크다.stackalloc 버퍼의 주소/참조를
new 배열을 쓰는 것이 더 낫다.stackalloc은 “성능/저수준 작업용 특수 도구” 정도로 생각하는 게 좋다.Span<byte>로 문자열 조작/파싱을 최적화할 때
그 외 대부분의 “일반적인” 코드에서는 stackalloc 없이도 충분하다.
stackalloc = “잠깐 쓸 작은 배열을 힙이 아니라 스택에 직접 만들어서
엄청 빠르게 쓰고, 메서드 끝나면 흔적도 없이 같이 날려버리는 키워드”