標準模式繁瑣:
struct person *p = malloc(sizeof(struct person));
if (!p) { fprintf(stderr, "malloc failed"); /* 處理錯誤 */ }
... free(p);
參考高級語言 new:分配失敗直接終止程序(內存耗盡時繼續運行意義不大)。構建統一入口宏,自動檢查、初始化、記錄調用位置。
// scalloc.h #ifndef _H_SIMPLEC_SCALLOC #define _H_SIMPLEC_SCALLOC #include <stdlib.h> // 內部函數(帶文件/行/函數信息) void sm_free_(void *ptr, const char *file, int line, const char *func); void *sm_malloc_(size_t sz, const char *file, int line, const char *func); void *sm_realloc_(void *ptr, size_t sz, const char *file, int line, const char *func); // 公開宏(自動填充 __FILE__ __LINE__ __func__) #define sm_free(ptr) sm_free_(ptr, __FILE__, __LINE__, __func__) #define sm_malloc(sz) sm_malloc_(sz, __FILE__, __LINE__, __func__) #define sm_calloc(n, sz) sm_malloc_((n)*(sz), __FILE__, __LINE__, __func__) #define sm_realloc(p, sz) sm_realloc_(p, sz, __FILE__, __LINE__, __func__) // 可選:全局替換標準函數名 #ifndef _SIMPLEC_SCALLOC_CLOSE #define free sm_free #define malloc sm_malloc #define calloc sm_calloc #define realloc sm_realloc #endif #endif

typedef enum { HF_Alloc, HF_Free } header_e;
struct header {
header_e flag; // 狀態標記
int line; // 分配行號
const char *file; // 文件名
const char *func; // 函數名
};
每次分配在用戶內存前插入 struct header(16-24 字節開銷),用於雙重釋放檢測、洩漏定位。
void *sm_malloc_(size_t sz, const char *file, int line, const char *func) {
struct header *h = malloc(sz + sizeof(struct header));
if (!h) {
fprintf(stderr, "%s:%d:%s alloc fail\n", file, line, func);
exit(EXIT_FAILURE);
}
h->flag = HF_Alloc; h->line = line; h->file = file; h->func = func;
memset(h + 1, 0, sz); // 返回用戶區並清零
return h + 1;
}
static struct header *_header_get(void *ptr, const char *file, int line, const char *func) {
struct header *h = (struct header *)ptr - 1;
if (h->flag != HF_Alloc) {
fprintf(stderr, "%s:%d:%s double/invalid free flag=%d\n", file, line, func, h->flag);
exit(EXIT_FAILURE);
}
return h;
}
void *sm_realloc_(void *ptr, size_t sz, const char *file, int line, const char *func) {
if (!ptr) return sm_malloc_(sz, file, line, func);
struct header *h = _header_get(ptr, file, line, func);
h->flag = HF_Free;
struct header *nh = realloc(h, sz + sizeof(struct header));
nh->flag = HF_Alloc; nh->line = line; nh->file = file; nh->func = func;
return nh + 1;
}
void sm_free_(void *ptr, const char *file, int line, const char *func) {
if (ptr) {
struct header *h = _header_get(ptr, file, line, func);
h->flag = HF_Free;
free(h);
}
}
// main.c
#include "scalloc.h"
int main() {
int *p = malloc(10); free(p);
puts("start test...");
free(p); // 故意雙重釋放觸發檢測
getchar(); return 0;
}

輸出顯示精確定位到文件、行號、函數,且識別出 flag 異常。
flag(4)+line(4)+file(8)+func(8),對齊後)。核心思想:偷梁換柱——在用戶內存前植入元數據,統一入口宏自動捕獲上下文,失敗即退出,釋放時驗證完整性。可直接集成到項目構建系統中替換標準分配器。
