Matasano 博客将“检查返回值malloc()
”称为“C 编程反成语”。相反,如果它失败了,它malloc()
应该自动调用你。abort()
论点是,由于您通常希望在程序malloc()
失败时中止程序,因此这应该是默认行为,而不是您每次都必须费力地键入或忘记键入的内容。
在不深入了解这个想法的优点的情况下,最简单的设置方法是什么?我正在寻找可以通过其他库函数自动检测内存分配失败的东西,例如asprintf()
。一个便携的解决方案会很棒,但我也会对特定于 mac 的东西感到满意。
总结以下最佳答案:
Mac 运行时解决方案
在运行程序之前设置MallocErrorAbort=1
环境变量。自动适用于所有内存分配功能。
Mac/linux 运行时解决方案
使用动态库 shim在运行时使用或加载自定义malloc()
包装器。您可能想要换行, , & c。也是。LD_PRELOAD
DYLD_INSERT_LIBRARIES
calloc()
realloc()
Mac/linux编译解决方案
定义您自己的malloc()
和free()
函数,并使用dyld(RTLD_NEXT, "malloc")
如下所示访问系统版本。同样,您可能想要换行calloc()
, realloc()
, & c。也是。
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
void *(*system_malloc)(size_t) = NULL;
void* malloc(size_t bytes) {
if (system_malloc == NULL) {
system_malloc = dlsym(RTLD_NEXT, "malloc");
}
void* ret = system_malloc(bytes);
if (ret == NULL) {
perror("malloc failed, aborting");
abort();
}
return ret;
}
int main() {
void* m = malloc(10000000000000000l);
if (m == NULL) {
perror("malloc failed, program still running");
}
return 0;
}
Linux编译解决方案
按照glibc 手册中的说明使用__malloc_hook
和。__realloc_hook
mac编译解决方案
使用该malloc_default_zone()
函数访问堆的数据结构,取消保护内存页面,并在 中安装一个钩子zone->malloc
:
#include <malloc/malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
static void* (*system_malloc)(struct _malloc_zone_t *zone, size_t size);
static void* my_malloc(struct _malloc_zone_t *zone, size_t size) {
void* ret = system_malloc(zone, size);
if (ret == NULL) {
perror("malloc failed, aborting");
abort();
}
return ret;
}
int main() {
malloc_zone_t *zone = malloc_default_zone();
if (zone->version != 8) {
fprintf(stderr, "Unknown malloc zone version %d\n", zone->version);
abort();
}
system_malloc = zone->malloc;
if (mprotect(zone, getpagesize(), PROT_READ | PROT_WRITE) != 0) {
perror("munprotect failed");
abort();
}
zone->malloc = my_malloc;
if (mprotect(zone, getpagesize(), PROT_READ) != 0) {
perror("mprotect failed");
abort();
}
void* m = malloc(10000000000000000l);
if (m == NULL) {
perror("malloc failed, program still running");
}
return 0;
}
为了完整起见,您可能还需要包装calloc()
,和 in中realloc()
定义的其他函数。malloc_zone_t
/usr/include/malloc/malloc.h