OS X で malloc()、calloc()、free() などをオーバーライドするにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/929893

質問

最新の XCode と GCC を想定して、メモリ割り当て関数をオーバーライドする適切な方法は何ですか (演算子 new/delete も同様だと思います)。デバッグ メモリ アロケータはゲームには遅すぎるため、最小限の影響で自分で実行できる基本的な統計情報が必要なだけです。

Linux ではフックのおかげで簡単であることはわかっていますが、私が HeapManager を書いた 10 年前の codewarrior ではこれは簡単なことでした。

残念ながら、smartheap には Mac バージョンがありません。

正しい解決策はありません

他のヒント

実行中のプログラムを変更する必要がないため、このタスクにはライブラリのプリロードを使用します。これを行う通常の Unix 方法に慣れている場合は、LD_PRELOAD を DYLD_INSERT_LIBRARIES に置き換えるだけで済みます。

最初のステップは、次のようなコードを含むライブラリを作成し、次に通常の共有ライブラリ リンク オプションを使用してそれをビルドすることです (gcc -dynamiclib):

void *malloc(size_t size)
{
    void * (*real_malloc)(size_t);
    real_malloc = dlsym(RTLD_NEXT, "malloc");

    fprintf(stderr, "allocating %lu bytes\n", (unsigned long)size);
    /* Do your stuff here */

    return real_malloc(size);
}

転用する場合も注意してください calloc() とその実装呼び出し malloc(), 、どのように呼び出されているかを確認するために追加のコードが必要になる場合があります。C++ プログラムはかなり安全であるはずです。 new オペレーターコール malloc() いずれにしても、それを強制する標準はないことに注意してください。を使用しない実装に遭遇したことはありません malloc(), 、 けれど。

最後に、プログラムの実行環境をセットアップして起動します (シェルが環境変数を処理する方法に応じて調整が必要になる場合があります)。

export DYLD_INSERT_LIBRARIES=./yourlibrary.dylib
export DYLD_FORCE_FLAT_NAMESPACE=1
yourprogram --yourargs

見る dyld マニュアルページ 動的リンカー環境変数の詳細については、「」を参照してください。

この方法はかなり一般的です。ただし、次のような制限があります。

  • 直接のシステムコールを迂回することはできなくなります
  • アプリケーション自体が以下を使用してユーザーを騙す場合、 dlsym() ロードする mallocのアドレスの場合、通話は転送されません。ただし、注意をそらして騙し戻さない限り、 dlsym!

ずっと10.7で検索する(ここでは含まれています)との問題の後、私はこのトピックに関するブログ記事を書くことにしました:<のhref = "http://bkdc.ubiquity.ro/2011/07/how-to-set- malloc関数-フック・イン・OSX-ライオン-107.html」のrel = "nofollowを">でのmallocフックを設定する方法OSXライオンの

あなたはこのトピックに関するより多くの情報を記事の最後にいくつかの良いリンクを見つけることができます。

基本的な解決策ます:

malloc_zone_t *dz=malloc_default_zone();
if(dz->version>=8)
{
    vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ | VM_PROT_WRITE);//remove the write protection
}
original_free=dz->free;
dz->free=&my_free; //this line is throwing a bad ptr exception without calling vm_protect first
if(dz->version==8)
{
    vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ);//put the write protection back
}

これは古い質問ですが、自分でこれを試みているときに見つけました。私は、主に、自動的に割り当てが解除されると思っていたものが適切に割り当て解除されていることを確認するために、取り組んでいた個人プロジェクトでこのトピックに興味を持ちました。結局、割り当てられたヒープの量を追跡し、必要に応じてレポートできるようにする C++ 実装を作成することになりました。

https://gist.github.com/monitorjbl/3dc6d62cf5514892d5ab22a59ff34861

名前が示すように、これは OSX 固有です。ただし、Linux 環境では、次のコマンドを使用してこれを行うことができました。 malloc_usable_size

#define MALLOC_DEBUG_OUTPUT
#include "malloc_override_osx.hpp"

int main(){
   int* ip = (int*)malloc(sizeof(int));
   double* dp = (double*)malloc(sizeof(double));

   free(ip);
   free(dp);
}

建物

$ clang++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk \
          -pipe -stdlib=libc++ -std=gnu++11 -g -o test test.cpp
$ ./test
0x7fa28a403230 -> malloc(16) -> 16
0x7fa28a403240 -> malloc(16) -> 32
0x7fa28a403230 -> free(16) -> 16
0x7fa28a403240 -> free(16) -> 0

これが将来他の人に役立つことを願っています。

あなたが必要とする基本的な統計情報を迅速(とちょっと汚い)トリックはいくつかの#defineマクロ置換を使用している、単純なラッパーに収集することができることができます。

void* _mymalloc(size_t size)
{
    void* ptr = malloc(size);

    /* do your stat work? */

    return ptr;
}

#define malloc(sz_) _mymalloc(sz_)

:マクロは、に定義されている場合、 _mymalloc定義は、それが無限再帰であなたを残して、その関数の内部でmalloc関数呼び出しを置き換えるに終わる...そう、これを確保する前に、そうではありません。あなたは明示的にその関数定義の前にそれを#undefと単純に(再)あなたはそれがうまくいけば、このような状況を回避するために含めてしまう場所に応じて、後でそれを定義することもできます。

私は)(あなたはmalloc関数を定義した場合(だと思う)と無料の独自の.cファイルにリンカがそのバージョンを解決しますプロジェクトに含まれます。

さて、どのようにmalloc関数を実装するつもりですか?

Hoard メモリ アロケータの作者である Emery Berger による、OSX 上のアロケータを置き換えるアプローチを次の URL で確認してください。 https://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cpp (および、インクルードをたどることで自分自身を追跡できる他のいくつかのファイル)。

これはアレックスの答えを補足するものですが、この例はシステムが提供するアロケーターを置き換えるというより本質的なものだと思いました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top