malloc/free 或 new/delete,向高址增長,非連續。static 變量。初始化與未初始化分段。int a = 0; // 全局初始化區
char *p1; // 全局未初始化區
int main() {
int b; // 棧
char s[] = "abc";// 棧(陣列內容複製至此)
char *p2; // 棧
char *p3 = "123456"; // "123456" 在常量區,p3 在棧
static int c = 0; // 全局靜態初始化區
p1 = malloc(10); // 10 bytes 在堆
p2 = malloc(20); // 20 bytes 在堆
strcpy(p1, "123456"); // 複製到堆,常量區可能合併優化
}
| 維度 | 棧 | 堆 |
|---|---|---|
| 分配方式 | 編譯器自動 | 程序員手動 |
| 釋放方式 | 自動(函數返回) | 手動(free/delete) |
| 空間大小 | 固定(Win 預設 1-2MB) | 受限於虛擬記憶體,極大 |
| 生長方向 | 向低地址 | 向高地址 |
| 碎片問題 | 無 | 易產生碎片 |
| 分配速度 | 極快(指針移動) | 較慢(鏈表遍歷) |
| 存取效率 | 高(連續、熱點在缓存) | 較低(間接寻址) |
函數調用時入棧順序:
ebp(建立棧幀鏈)返回時逆序出棧,恢復 esp/ebp,跳回返回地址。
free 精確釋放char c[] = "1234567890"; // 棧上陣列
char *p = "1234567890"; // 指向常量區
a = c[1]; // 反組譯:mov cl, [ebp-0Fh] → 直接索引
a = p[1]; // 反組譯:mov edx, [ebp-14h]; mov al, [edx+1] → 間接兩步
棧上陣列直接偏移寻址,指針需先取指針值再偏移,指令更多、更慢。
文中「堆/棧」指作業系統記憶體管理區域,與數據結構中的堆(優先隊列)、棧(LIFO 結構)是完全不同的兩組概念。