在僅擁有 512KB RAM 的嵌入式系統中,動態內存碎片化是穩定性殺手。標準庫無「查詢可用塊」API,本文提供一個實用偵察函數:通過**遞減嘗試 `malloc`** 探測當前堆中每個可分配塊大小,統計總可用內存、塊數量、最大塊,幫助定位碎片化嚴重程度與內存洩漏。
#define MAX_MEM (512 * 1024) // 系統總 RAM 上限
#define MAX_MEM_PIECES 200 // 最大記錄塊數
#define MIN_MEM 512 // 最小探測粒度 512B
void ct_CalcFreeMem(void) {
int curFreeSize = MAX_MEM;
int *pt = NULL;
int *ptArray[MAX_MEM_PIECES];
int i = 0, j = 0;
int totalMem = 0;
printf("====================\n");
// 1. 遞減探測:從最大塊嘗試分配,成功則記錄並繼續嘗試更小塊
while (1) {
pt = (int *)malloc(curFreeSize);
if (pt != NULL) {
printf("Free mem slice %d = %d B\n", i, curFreeSize);
ptArray[i] = pt; // 暫存指針,防止被合併/釋放
pt = NULL;
i++;
totalMem += curFreeSize;
}
curFreeSize -= MIN_MEM; // 步進 512B
if (curFreeSize < MIN_MEM) break;
}
// 2. 釋放所有探測分配的塊,還原堆狀態
for (j = 0; j < i; j++) {
if (ptArray[j]) {
free(ptArray[j]);
ptArray[j] = NULL;
}
}
printf("Total free mem = %d B\n", totalMem);
printf("====================\n");
}
====================
Free mem slice 0 = 122880 B
Free mem slice 1 = 61440 B
Free mem slice 2 = 30720 B
Free mem slice 3 = 15360 B
Free mem slice 4 = 7680 B
Free mem slice 5 = 3840 B
Free mem slice 6 = 1920 B
Free mem slice 7 = 960 B
Free mem slice 8 = 512 B
Total free mem = 245760 B
====================
| 宏 | 含義 | 調優建議 |
|---|---|---|
| `MAX_MEM` | 探測上限 | 設為已知堆大小或 `malloc_usable_size(0)` 估算值 |
| `MIN_MEM` | 步進粒度 | 512B 平衡速度/精度;小系統可降至 64B/128B |
| `MAX_MEM_PIECES` | 最大記錄塊數 | 預估最大碎片數 + 余量;超限會漏統計 |