| 概念 | 堆疊 | 堆積 |
|---|---|---|
| 管理方式 | LIFO、編譯器/執行期自動 | GC 追蹤、非連續配置 |
| 配置速度 | 極快 (指標遞增) | 較慢 (搜尋空閒區塊) |
| 存活期 | 方法/區塊返回即釋放 | GC 判定不可觸及回收 |
| 大小限制 | ~1MB (執行緒堆疊) | 虛擬記憶體上限 |
| 存放內容 | 區域變數、參數、回傳位址、實值型別實例 | 參考型別物件、陣列、委派、閉包、String、Boxed 實值型別 |
// 實值型別:直接包含資料
int a = 10; // 堆疊:[10]
struct Point { int X, Y; }
Point p = new Point(); // 堆疊:[0, 0] (預設值)
Point p2 = p; // 複製:堆疊新增 [0, 0]
// 參考型別:變數存參考,物件在堆積
class Person { public string Name; }
Person p1 = new Person(); // 堆疊:[ref] → 堆積:[Name=null]
Person p2 = p1; // 複製參考:堆疊新增 [ref] → 同一堆積物件
p2.Name = "John"; // p1.Name 也變 "John"
int val = 42;
object boxed = val; // Boxing: 配置堆積物件、複製值、存參考
int unboxed = (int)boxed; // Unboxing: 檢查型別、複製值回堆疊
// 效能影響:配置記憶體、GC 壓力、複製開銷
// 避免:泛型集合 List vs ArrayList、介面呼叫裝箱
List list = new List(); // 無裝箱
list.Add(42); // 直接存儲
ArrayList aList = new ArrayList(); // 裝箱
aList.Add(42); // 配置物件、複製
Thread Stack (向下增長)
┌─────────────────────┐
│ Main Frame │ ← Stack Pointer (RSP/ESP)
│ - args │
│ - locals: a=10 │
│ - ref: p1 ─────────┼──┐
└─────────────────────┘ │
▼
Managed Heap
┌─────────────────────┐
│ Person Object │
│ - TypeHandle │
│ - SyncBlockIndex │
│ - Name = "John" │ ← p1, p2 參考此處
└─────────────────────┘
// stackalloc: 堆疊配置陣列 (C# 7.2+ 安全語境)
Span stackArray = stackalloc int[100]; // 無 GC、極快、大小受限
// Memory: 可跨非同步邊界的緩衝區抽象
Memory buffer = new byte[4096];
await stream.ReadAsync(buffer); // 直接寫入
// 字串切片零複製
ReadOnlySpan slice = "Hello World".AsSpan(6, 5); // "World"
Span、實值型別介面約束stackalloc / ArrayPool / ObjectPooldotnet-gcdump, dotnet-trace, BenchmarkDotNet

