三種分配方式
- 靜態儲存區:編譯期分配,程式全生命週期存在。如全域變數、
static 變數。
- 棧:函式執行時自動分配區域變數、參數、返回位址;函式結束自動釋放。效率極高,但容量有限(Windows 預設 1~2MB)。
- 堆:執行期透過
malloc/new 任意申請,程式設計師負責 free/delete 釋放。靈活但易產生碎片與洩漏。
程式記憶體五大區域
- 程式碼區:二進位指令
- 全域/靜態區:全域變數、靜態資料、常數
- 常數字串區:字串字面值
- 堆區:動態分配
- 棧區:函式幀、區域變數
程式碼範例解析
int a = 0; // 全域初始化區
char *p1; // 全域未初始化區
int main() {
int b; // 棧
char s[] = "abc";// 棧
char *p2; // 棧
char *p3 = "123456"; // "123456" 在常數區,p3 在棧
static int c = 0;// 全域/靜態初始化區
p1 = new char[10]; // 堆
p2 = new char[20]; // 堆
strcpy(p1, "123456"); // 常數區字串複製到堆
}
堆與棧詳細比較
| 維度 | 棧 | 堆 |
| 申請方式 | 系統自動 | 程式設計師手動 (malloc/new) |
| 回應機制 | 空間足夠即給,否則棧溢位 | 遍歷空閒鏈表尋找合適區塊,記錄大小於區塊頭 |
| 大小限制 | 固定 (Windows ~1-2MB) | 受限於虛擬記憶體,幾乎無上限 |
| 分配效率 | 極高 (指令集支援) | 較慢,易產生碎片 |
| 存取效率 | 陣列直接索引,快 | 指針間接存取,慢 |
| 生長方向 | 向低位址 | 向高位址 |
| 碎片問題 | 無 (先進後出) | 頻繁 new/delete 產生碎片 |
new/delete vs malloc/free
new 呼叫建構函式,delete 呼叫解構函式;malloc/free 僅分配/釋放原始記憶體。
- 陣列
new T[N] 僅能呼叫預設建構函式。
- 範例程式碼驗證:
malloc 配置 Time 物件不呼叫建構/解構,new 則會。
建議
- 優先使用棧 (區域變數、
std::vector 等 RAII 容器)。
- 大塊/生命週期不固定記憶體才用堆,並善用智慧指標 (
unique_ptr, shared_ptr) 自動管理。
- 嚴防越界,寧可崩潰也不可破壞堆/棧結構。