Linux/GCC/C++ では、malloc/free/new/delete が呼び出されるたびに何かを stderr に記録したいと考えています。ライブラリのメモリ割り当てを理解しようとしているので、単体テストの実行中にこの出力を生成したいと思います。メモリ リークの検出に valgrind を使用していますが、割り当てだけをログに記録するオプションが見つかりません。
何か案は?可能な限り簡単な解決策を探しています。ライブラリの再コンパイルはオプションではありません。
ltrace を使用して malloc/free の呼び出しを追跡できます。
#include <stdlib.h>
int main (void)
{
void *ptr = malloc(10);
free(ptr);
return 0;
}
$ g++ test.cpp -o test
$ ltrace -e malloc,free ./test
malloc(10) = 0x804a008
free(0x804a008) = <void>
+++ exited (status 0) +++
再コンパイルせずに新規/削除呼び出しをトレースするには、おそらく LD_PRELOAD のようなものを使用して独自のバージョンで呼び出しをオーバーライドする必要があります。
malloc_hook(3)
独自の関数をグローバルに挿入できますmalloc
。(__realloc_hook
__free_hook
などもありますが、簡単にするために省略しました。)
#include <stdio.h>
#include <malloc.h>
static void *(*old_malloc_hook)(size_t, const void *);
static void *new_malloc_hook(size_t size, const void *caller) {
void *mem;
__malloc_hook = old_malloc_hook;
mem = malloc(size);
fprintf(stderr, "%p: malloc(%zu) = %p\n", caller, size, mem);
__malloc_hook = new_malloc_hook;
return mem;
}
static void init_my_hooks(void) {
old_malloc_hook = __malloc_hook;
__malloc_hook = new_malloc_hook;
}
void (*__malloc_initialize_hook)(void) = init_my_hooks;
$ cat >mem.c <<'EOF' (上記のコード) EOF $ cc -fPIC -shared -o mem.so mem.c $ LD_PRELOAD=./mem.sols 0x7ffc14931adc: malloc(5) = 0xb40010 0x7ffc1492c6b0: malloc(120) = 0xb40030 0x7ffc1497f61a: malloc(12) = 0xb40010 0x7ffc1492be38: malloc(776) = 0xb400b0 …
printf
を呼び出す可能性がmalloc
あるため、フックを一時的に元に戻します。malloc
何らかの方法でフックする場合は、これに注意してください。
私はこれを自分でテストしていませんが、これらがうまくいくと確信しています:
ライブラリを再コンパイルしたくないので、意味のある出力 (vs. 単に「23 バイトの新規呼び出し」) を提供するには、スタック トレースを取得する必要がある場合があります。関数を使用してスタックをナビゲートしたことを覚えていますが、今はそれらを見つけることができません。おそらく、system() と pstack(1) を呼び出すとうまくいくでしょう。
演算子 new と delete を再定義して、この新しい定義を std c++ ライブラリの前に置くことができます。これは、問題のライブラリが使用しているコンテナおよび標準コンポーネントからの呼び出しをキャプチャしない場合があります。これには再リンクが必要です。
LD_PRELOAD を使用して、演算子 new と delete を動的に変更できます。アプリケーションが動的にリンクされている場合、再リンクは必要ありません。
これらのポインタがお役に立てば幸いです。レシピがなくて申し訳ありません。