理論上可分配 2GB 陣列,但實際受碎片、共享庫、棲增長限制,可用連續空間遠小於此。
| 區域 | 別名 | 內容 | 生命週期 | 分配方向 |
|---|---|---|---|---|
| 基棧 | 靜態存儲區 / .data .bss .text | 全局/靜態變量、常量、代碼指令 | 程序啟動~結束 | 編譯期固定 |
| 浮動棧 | 棧 / Stack | 函數參數、局部變量、返回地址、保存寄存器 | 函數調用~返回 | 高地址 → 低地址 (向下增長) |
| 堆 | Heap | malloc/new 分配的動態記憶體 | 手動 free/delete 釋放 | 低地址 → 高地址 (向上增長) |
free(p); p = NULL;。strcpy/sprintf 無長度檢查 → 用 strncpy/snprintf/memcpy_s。-fsanitize=address)、運行時檢測 (Valgrind, Electric Fence)。free(p); free(p); → 置 NULL 防禦。free(&local_var); → 靜態分析工具檢查。[c]
// 錯誤
for (p = head; p; p = p->next) free(p); // p->next 讀取已釋放記憶體
// 正確
struct node *p, *tmp;
for (p = head; p; p = tmp) {
tmp = p->next;
free(p);
}
[c]
// 錯誤:主執行緒棧上結構體,函數返回後棧幀銷毀,子執行緒讀到垃圾值
void start_thread_wrong() {
Param param = { .fd = sock };
pthread_create(&tid, NULL, worker, ¶m); // 傳棧地址!
}
// 正確:堆上分配,子執行緒用完負責 free
void start_thread_right() {
Param *param = malloc(sizeof(Param));
param->fd = sock;
pthread_create(&tid, NULL, worker, param);
}
void* worker(void *arg) {
Param *p = (Param*)arg;
// ... 使用 p->fd
free(p); // 子執行緒釋放
return NULL;
}
-Wall -Wextra -Werror -fsanitize=address,undefined。