该Matasano博客呼吁"检查的返回值malloc()"一"C程序反成语."相反malloc()应该自动调用abort()如果失败了你.这个论点是,因为如果malloc()失败,你通常会想要中止程序,这应该是默认行为,而不是你必须费力地键入的东西 - 或者可能忘记输入!-every time.
没有深入了解这个想法的优点,最简单的方法是什么?我正在寻找能够自动检测其他库函数的内存分配失败的东西asprintf().便携式解决方案会很精彩,但我也会对特定于mac的东西感到满意.
总结下面的最佳答案:
MallocErrorAbort=1在运行程序之前设置环境变量.自动适用于所有内存分配功能.
使用动态库填充malloc()程序在运行时使用LD_PRELOAD或加载自定义包装器DYLD_INSERT_LIBRARIES.你可能会想包装calloc(),realloc(),和温度.同样.
定义您自己的malloc()和free()功能,并使用dyld(RTLD_NEXT, "malloc") 此处所示访问系统版本.同样,你可能会想包装calloc(),realloc(),和温度.同样.
#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;
}
Run Code Online (Sandbox Code Playgroud)
使用__malloc_hook和__realloc_hook如glibc手册中所述.
使用该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;
}
Run Code Online (Sandbox Code Playgroud)
为了完整起见,你可能会想包装calloc(),realloc()以及在规定的其它功能malloc_zone_t中/usr/include/malloc/malloc.h也是如此.
只需包含malloc()一些my_malloc()执行此操作的函数.在很多情况下,它实际上可能处理不能分配内存,因此这种行为是不可取的.添加功能很容易,malloc()但不能删除它,这可能就是它以这种方式运行的原因.
另外要记住的是,这是一个你正在调用的库.你想要一个图书馆电话,并让图书馆杀死你的应用程序,而你却无法发表意见吗?
我想我错过了关于asprintf但是libc导出了一些你可以使用的钩子(valgrind本质上是什么)让你覆盖malloc行为.这里是钩子本身的参考,如果你足够了解C,那就不难了.
http://www.gnu.org/savannah-checkouts/gnu/libc/manual/html_node/Hooks-for-Malloc.html