Appearance
带
x前缀的内存分配包装器 —— 分配失败时直接退出程序,省去每个调用点重复的 NULL 检查。
为什么需要 xmalloc
C 语言的 malloc 失败时返回 NULL,理论上每次调用都要检查:
c
// 没有 xwrapper 时:
void *p = malloc(size);
if (p == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
// ... 每次调用都要重复这三行ds4.c 有几百处内存分配,重复的 NULL 检查让代码膨胀且容易遗漏。xmalloc 把错误处理集中到一处,调用点只写 p = xmalloc(size)。
核心原理
xmalloc(size) → malloc(size) + NULL → fprintf + exit(1)
xcalloc(n, s) → calloc(n, s) + NULL → fprintf + exit(1)
xrealloc(p, s) → realloc(p,s) + NULL → fprintf + exit(1)为什么没有 xfree?释放 NULL 是安全的(free(NULL) 是 no-op),不需要包装。
在 ds4.c 中的实现
c
// ds4.c — xwrapper 家族
void *xmalloc(size_t size) {
void *p = malloc(size);
if (!p) { fprintf(stderr, "xmalloc: out of memory\n"); exit(1); }
return p;
}特别注意 xmalloc_zeroed:
c
void *xmalloc_zeroed(size_t size) {
void *p = xmalloc(size);
memset(p, 0, size); // 手动清零
return p;
}为什么不用 xcalloc?Darwin 内核对大块 calloc 使用共享零页(CoW zero page)——物理内存只在首次写入时分配。这把大量 page fault 延迟到推理阶段,在 macOS 上可能导致内核 panic。malloc + memset 立即触发所有 page fault,在启动阶段集中处理。
相关概念
- page-fault — xmalloc_zeroed 避免 calloc 的延迟 page fault 陷阱
- mmap — 模型数据通过 mmap 零拷贝加载,不经过 xmalloc