內存區域速覽
| 區域 | 特點 | 典型內容 |
| 棧 | 自動管理,函數調用分配/釋放,速度快,空間小 | 局部變量、函數參數、返回地址 |
| 堆 | 手動管理,malloc/free,空間大,易產生碎片 | 動態分配內存 |
| 靜態/全局區 | 程序啟動分配,結束釋放 | 全局變量、static 變量、字面量 |
四大核心函數原型與用法
1. malloc(size_t size) — 原始分配
void *malloc(size_t size); // 返回 void*,需強轉
int *p = (int *)malloc(10 * sizeof(int));
if (!p) { /* 處理失敗 */ }
- 不初始化內存(垃圾值)。
- 失敗返回
NULL,必須檢查。
2. calloc(size_t nmemb, size_t size) — 零初始化分配
void *calloc(size_t nmemb, size_t size); // 分配 nmemb * size 字節並清零
int *arr = (int *)calloc(100, sizeof(int)); // 等價 malloc(400) + memset(0)
- 自動清零,適合數組/結構體初始化。
- 內部可能優化(如映射零頁),比 malloc+memset 更快。
3. free(void *ptr) — 釋放
free(p);
p = NULL; // 防止野指針,雙重釋放
- 只能釋放 malloc/calloc/realloc 返回的地址。
- 釋放後指針不自動置 NULL,手動置 NULL 是良習。
- 釋放
NULL 安全無操作。
4. realloc(void *ptr, size_t size) — 調整大小
void *realloc(void *ptr, size_t size);
typedef 輔助類型定義(提升可移植性)
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
// 推薦直接 #include 使用標準類型
位域:節省空間的利器
struct flags {
unsigned int a : 1; // 1 bit
unsigned int : 2; // 2 bit 填充/保留
unsigned int b : 3;
unsigned int c : 2;
}; // 共 8 bits = 1 字節
- 位域長度不能超過底層類型位寬。
:0 強制下一位域從新字節開始。
- 位域不取地址,不可用指針指向。
避坑指南:內存洩漏四大元兇
- 忘記 free:動態分配無釋放路徑。
- realloc 失敗未保留舊指針(上文詳述)。
- 指針算術導致丟失基址:
p++ 後無法 free,務必保存原指針。
- 早釋放/多釋放:使用後置 NULL、引用計數或智能指針(C++)管理生命週期。
工具推薦
- Valgrind:
valgrind --leak-check=full ./prog 精準定位洩漏。
- AddressSanitizer:
gcc -fsanitize=address 編譯期插桿,運行時檢測越界/使用後釋放。