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()
を使用してシステム バージョンにアクセスします。ここでも、、、およびcをラップしたいと思うでしょう。同じように。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;
}
Linux コンパイル済みソリューション
glibc マニュアルの説明に従って__malloc_hook
andを使用します。__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()
完全を期すために、 、 、および で定義されrealloc()
ているその他の関数もラップすることをお勧めします。malloc_zone_t
/usr/include/malloc/malloc.h