7

Upstart initプロセス(pid 1)でメモリリークが発生しましたが、デバッグ時にどのようなオプションがありますか?

編集:これのためのいくつかの実際のツールを私に提案してください、手動でprintfsを置くか、手動でメモリ割り当てを計算することはそれをカットするつもりはありません。また、initコアをダンプして、それをいじくり回すことは、実際にはオプションではありません。

UPD1: valgrindが機能しません。カーネルコマンドラインの/sbin/initを適切なvalgrind+initマジックに置き換えることは、smapのselfの/ procにアクセスしようとするため、オプションではないようですが、initが実行される前は利用できません。

UPD2: dmallocも機能しません(ARMではコンパイルされません)。

4

5 に答える 5

8

貧乏人の解決策は、すべての呼び出しmallocfreeログに記録してから、ログを調べてパターンを探すことです。

ldここで役立つ可能性のある素晴らしい機能を提供します。

--wrap=symbol

シンボルのラッパー関数を使用します。シンボルへの未定義の参照は、「__wrap_symbol」に解決されます。「__real_symbol」への未定義の参照はすべてsymbolに解決されます。

これは、システム関数のラッパーを提供するために使用できます。ラッパー関数は「__wrap_symbol」と呼ばれる必要があります。システム関数を呼び出したい場合は、「__real_symbol」を呼び出す必要があります。

簡単な例を次に示します。

void *
__wrap_malloc (size_t c)
{
   printf ("malloc called with %zu\n", c);
   return __real_malloc (c);
}

--wrap mallocを使用して他のコードをこのファイルにリンクすると、「malloc」へのすべての呼び出しは、代わりに関数「__wrap_malloc」を呼び出します。「__wrap_malloc」で「__real_malloc」を呼び出すと、実際の「malloc」関数が呼び出されます。

--wrapオプションのないリンクが成功するように、「__real_malloc」関数も提供することをお勧めします。これを行う場合は、「__real_malloc」の定義を「__wrap_malloc」と同じファイルに入れないでください。そうした場合、リンカが呼び出しを「malloc」にラップする前に、アセンブラが呼び出しを解決する可能性があります。


アップデート

これがどのように役立つかを明確にするためだけに。

  • Upstartのビルドにカスタムファイルを追加します。

このような:

void*__wrap_malloc( size_t c )
{
   void *malloced = __real_malloc(c);
   /* log malloced with its associated backtrace*/
   /* something like: <malloced>: <bt-symbol-1>, <bt-symbol-2>, .. */
   return malloced
}

void __wrap_free( void* addr )
{
   /* log addr with its associated backtrace*/
   /* something like: <addr>: <bt-symbol-1>, <bt-symbol-2>, .. */
   __real_free(addr);
}
  • upstartをデバッグシンボル(-g)で再コンパイルして、いくつかの優れたバックトレースを取得できるようにします。-O2/-O3必要に応じて、コードを最適化()することもできます。

  • Upstartを追加の、とリンクしLD_FLAGS --wrap=mallocます--wrap=free
    これで、 Upstartが呼び出す場所ならどこでもmalloc、シンボルは魔法のように新しいシンボルに解決されます__wrap_malloc。美しく、これはリンク時に発生するため、コンパイルされたコードに対してすべて透過的です。それは、混乱のないシミングインストルメンテーション
    のようなものです。

  • リークが発生したことを確認するまで、通常どおり再コンパイルされたUpstartを実行します。

  • mallocedログを調べて、 sとsの不一致を探しaddrます。

いくつかのメモ:

  • この--wrap=symbol機能は、実際にはマクロである関数名では機能しません。だから気をつけろ#define malloc nih_malloc。これは、libnihを使用する必要があるもの--wrap=nih_mallocであり、__wrap_nih_malloc代わりに使用する必要があります。
  • gccの組み込みのバックトレース機能を使用します。
  • これらの変更はすべて、再コンパイルされたUpstart実行可能ファイルにのみ影響します。
  • 代わりにログをsqliteDBにダンプすると、不一致のmallocとfreeを簡単に見つけることができます。
  • SQL挿入ステートメントをログ形式にして、後で分析するためにデータベースに挿入することができます。
于 2010-10-11T16:51:14.890 に答える
2

initを変更せずに使用することもできますが、MALLOC_CHECK環境変数を1以上に設定するラッパーを作成します。これにより、いくつかのメモリ割り当て診断を確認できます。

バリエーションは、初期化ソースコードをわずかに変更して、mallocの使用を開始する前にその環境変数自体を設定することです。

AmineKが提案したように、initソースコード自体にデバッグコードを追加することもできます。

于 2010-10-11T10:52:32.260 に答える
2

malloc/free 呼び出しをフックし、割り当てるバイト数と毎回解放するバイト数をカウントすることで、メモリ割り当てを自分で計測できます。

于 2010-10-11T10:32:37.420 に答える
0

upstartのバージョンをGoogleのTCMallocにリンクしてみてください。ヒープチェッカーが組み込まれています。

ヒープチェッカーは、次の2つの方法で有効にできます。

  • 環境変数HEAPCHECKを{normal| 厳格| ドラコニアン}。
  • HEAPCHECKオブジェクトを使用して手動でコードを設定localおよびチェックしHeapProfileLeakCheckerます。

ただし、initの環境変数を設定する方法がわかりません。

于 2010-10-11T16:28:17.130 に答える
0

プロセスで pmap を実行し、どのメモリ セグメントが増加しているかを調べてみてはどうでしょうか。これにより、何がメモリを消費しているのかがわかります。少しスクリプトを書くだけで、このプロセスをほぼ自動化できます**。

** 前世で、 t秒間隔で実行中の一連のプロセスのn pmap スナップショットを取得するスクリプトを実際に作成しました。その出力は、サイズが変更されたセグメントを特定する perl スクリプトに入力されました。これを使用して、一部の商用コードでいくつかのメモリ リークを特定しました。[スクリプトを共有しますが、以前の雇用主の IP (著作権) で保護されています。]

  • ジョン
于 2010-10-14T18:29:00.020 に答える