最新のXCodeとGCCを想定して、メモリ割り当て関数をオーバーライドする適切な方法は何ですか(演算子new / deleteも同様だと思います)。デバッグメモリアロケータはゲームには遅すぎます。最小限の影響で自分で実行できるいくつかの基本的な統計が必要です。
Linuxではフックのおかげで簡単だと知っています。これは10年前にHeapManagerを書いたときのcodewarriorでは簡単なことでした。
悲しいことに、smartheapにはもうmacバージョンがありません。
最新のXCodeとGCCを想定して、メモリ割り当て関数をオーバーライドする適切な方法は何ですか(演算子new / deleteも同様だと思います)。デバッグメモリアロケータはゲームには遅すぎます。最小限の影響で自分で実行できるいくつかの基本的な統計が必要です。
Linuxではフックのおかげで簡単だと知っています。これは10年前にHeapManagerを書いたときの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);
}
Divertcalloc()
とその実装の呼び出しも行う場合はmalloc()
、呼び出し方法を確認するために追加のコードが必要になる場合があることに注意してください。new
とにかく演算子が呼び出すため、C++ プログラムはかなり安全なはずmalloc()
ですが、それを強制する標準はないことに注意してください。ただし、を使用しない実装に遭遇したことはありませんmalloc()
。
最後に、プログラムの実行環境をセットアップして起動します (シェルが環境変数を処理する方法によっては、調整が必要になる場合があります)。
export DYLD_INSERT_LIBRARIES=./yourlibrary.dylib
export DYLD_FORCE_FLAT_NAMESPACE=1
yourprogram --yourargs
動的リンカー環境変数の詳細については、dyld のマニュアル ページを参照してください。
この方法はかなり一般的です。ただし、制限があります。
dlsym()
アプリケーション自体が のアドレスをロードするために を使用してユーザーを騙した場合malloc
、呼び出しは転送されません。ただし、迂回して元に戻す場合を除きdlsym
ます。
http://lists.apple.com/archives/darwin-dev/2005/Apr/msg00050.htmlで言及されているmalloc_default_zone
手法は、まだ機能しているようです。たとえば、http ://code.google.com/p/fileview/source/ を参照してください。 Browse/trunk/fileview/fv_zone.cpp?spec=svn354&r=354を使用して、意図したものと似ていると思われる使用例を確認してください。
多くの検索 (ここに含まれています) と 10.7 に関する問題の後、このトピックに関するブログ投稿を書くことにしました: OSX Lion で malloc フックを設定する方法
投稿の最後に、このトピックに関する詳細情報を含むいくつかの優れたリンクがあります。
基本的な解決策:
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
これが将来他の誰かに役立つことを願っています!
プロジェクトに含まれている独自の.cファイルでmalloc()とfree()を定義すると、リンカーはそのバージョンを解決すると思います。
では、mallocをどのように実装するつもりですか?
Hoard メモリ アロケータの作成者である Emery Berger のhttps://github.com/emeryberger/Heap-Layers/blob/master/wrappers/macwrapper.cppで、OSX 上のアロケータを置き換えるためのアプローチを確認してください(およびいくつかのインクルードに従って自分でトレースできる他のファイル)。
これはアレックスの答えを補完するものですが、この例は、システムが提供するアロケーターを置き換えるという点でより適切だと思いました。
必要な基本的な統計情報を単純なラッパーで収集できる場合、手っ取り早い (そしてちょっと汚い) トリックは、#define
マクロ置換を使用することです。
void* _mymalloc(size_t size)
{
void* ptr = malloc(size);
/* do your stat work? */
return ptr;
}
と
#define malloc(sz_) _mymalloc(sz_)
注: マクロが_mymalloc 定義の前に定義されている場合、その関数内の malloc 呼び出しが置き換えられてしまい、無限再帰が発生します... そうでないことを確認してください。この状況を回避するために、関数定義の前に明示的#undef
に定義し、後でそれを含める場所に応じて単純に (再) 定義することをお勧めします。