私は大規模なプロジェクトで数か月間 tcmalloc を使用してきましたが、これまでのところ、メモリ リークを追跡して削除できる HeapProfiling 機能に非常に満足していると言わざるを得ません。
ここ数週間、アプリケーションでランダムなクラッシュが発生しましたが、ランダムなクラッシュの原因を見つけることができませんでした。非常に特殊な状況で、アプリケーションがクラッシュしたときに、アプリケーション スレッドの 1 つのスタックが完全に破損していることに気付きました。代わりに、スレッドが tcmalloc::PageHeap::AllocLarge() でスタックしていることが何度かわかりましたが、tcmalloc のデバッグ シンボルがリンクされていないため、何が問題なのか理解できませんでした。
ほぼ 1 週間の調査の後、今日、最も単純なことを試してみました。リンケージから tcmalloc を削除して使用しないようにし、何が起こったのかを確認しました。ええと...私は最終的に問題が何であるかを発見しました.問題のコードは次のように見えます:
void AllocatingFunction()
{
Object object_on_stack;
ProcessObject(&object_on_stack);
}
void ProcessObject(Object* object)
{
...
// Do Whatever
...
delete object;
}
libc を使用してもアプリケーションはクラッシュしましたが、最終的に、スタックに割り当てられたオブジェクトに対して delete を呼び出していることがわかりました。
私がまだ理解できないのは、この非常に危険な (完全に間違っていない場合) オブジェクトの割り当て解除と、AllocatingFunction が終了したときに object_on_stack が範囲外になったときの二重の割り当て解除にもかかわらず、tcmalloc が代わりにアプリケーションを実行し続けた理由です。実際のところ、問題のコードは、根底にある忌まわしさのヒントなしに繰り返し呼び出される可能性があります。
メモリの割り当て解除が適切に使用されていない場合の「未定義の動作」の 1 つであることは知っていますが、「標準」の libc と tcmalloc では動作が大きく異なることに驚きました。
tcmalloc がアプリケーションを実行し続ける理由について、何らかの洞察の説明がある人はいますか?
前もって感謝します :)
ごきげんよう