14

控えめに言っても、私は小さなメモリの問題を抱えており、原因を特定するためのツールやアイデアが不足しています。

4.4.4 以降および 4.7.1 より前の GCC で最適化されたコンパイルでスタック破壊の問題が発生した、高度にマルチスレッド化された (pthreads) C/C++ プログラムがあります。

症状は、スレッドの 1 つの作成中に、%RIP だけでなく、すべての親フレームとほとんどのレジスタが 0x00 またはその他の意味のないアドレスであるフル スタック スマッシュを取得することです。どのスレッドが問題を引き起こしているかはランダムに見えますが、ログ メッセージから判断すると、同じコードの塊に分離されているようで、新しいスレッドの作成である程度再現可能なポイントに来ているようです。

問題のあるファイル内の print() は、これまでのところ、アクティブなセクションを絞り込もうとする際に信頼できないことが証明されているため、これにより、問題のあるコードをトラップして、数千行の単一のコンパイル単位よりも狭く分離することが非常に困難になりました。 .

最終的にスタックを破壊するスレッドから派生するスレッドの作成は次のとおりです。

 
extern "C"
{
static ThreadReturnVal ThreadAPI WriterThread(void *act)
{
   Recorder       *rec = reinterpret_cast  (act);
   xuint64        writebytes;
   LoggerHandle m_logger = XXGetLogger("WriterThread");

   if (SetThreadAffinity(rec->m_cpu_mask))
   { ... }
   SetThreadPrio((xint32)rec->m_thread_priority);

   while (true)
   {
     ... poll a ring buffer ... Hard Spin 100% use on a single core, this is that sort of crazy code. 
   }
}

デバッグ ビルドを試しましたが、この症状は最適化されたビルド (-O2 以上) でのみ発生します。Valgrind/memcheck と DRD を試しましたが、どちらもスタックが吹き飛ばされる前に問題を見つけることができませんでした (障害が発生するまでに約 12 時間かかります)。

-O2 -Wstack-protector を使用してコンパイルすると何も問題はありませんが、-fstack-protector-all を使用してビルドするとバグから保護されますが、エラーは発生しません。

Electric-Fence もトラップしますが、それはスタックがなくなった後でのみです。

質問:問題のあるセクションを絞り込むには、他にどのようなツールや手法が役立ちますか?

どうもありがとう、 -- ビル

4

2 に答える 2

4

この種の問題にアプローチするためのいくつかのオプション:

破損が発生する前にスタック アドレスにハードウェア ブレークポイントを設定してみてください。デバッガーが破損の早い段階でブレークして、漠然と有用なデバッグ状態を提供することを期待できます。ここで難しいのは、適切なものを選択することですスタックアドレス; 問題のあるスレッドの「選択」がどれほどランダムかによっては、これは実用的ではない場合があります。しかし、あなたのコメントの1つから、新しく作成されたスレッドが破壊されることが多いように聞こえるので、これは実行可能かもしれません. スレッドの作成中に中断し、スレッドのスタックの場所を取得し、推測でオフセットし、ハードウェア BP を設定して続行します。休憩が早すぎるか、遅すぎるか、またはまったく休憩しないかに基づいて、オフセットを調整し、すすぎ、繰り返します. これは基本的に高度な推測とチェックであり、破損パターンがランダムすぎる場合は非常に妨げられたり、まったく実用的ではなくなったりする可能性があります。

もう 1 つのオプションは、クラッシュ ダンプの収集を開始することです。破損の原因を突き止めるのに役立つ可能性のあるクラッシュ ダンプ間のパターンを探してみてください。運が良ければ、クラッシュ ダンプの 1 つが「より速く」/「ソースに近い」状態でクラッシュする可能性があります。

残念ながら、これらの手法はどちらも科学というより芸術です。それらは非決定論的であり、健全な運に依存しているなどです(少なくとも私の経験では..そうは言っても、クラッシュダンプで驚くべきことを行うことができる人がいますが、それには多くの時間がかかりますそのレベルのスキルに到達するため)。

もう1つの補足事項:他の人が指摘したように、初期化されていないメモリはデバッグとリリースの違いの非常に典型的な原因であり、ここで簡単に問題になる可能性があります. ただし、留意すべきもう 1 つの可能性は、タイミングの違いです。スレッドがスケジュールされる順序とその期間は、多くの場合、デバッグとリリースで劇的に異なり、一方ではマスクされ、他方ではマスクされない同期バグに簡単につながる可能性があります。これらの違いは単に実行速度の違いによるものかもしれませんが、一部のランタイムはデバッグ環境で意図的にスレッド スケジューリングをいじっていると思います。

于 2012-10-03T22:59:10.573 に答える
2

静的分析ツールを使用して、いくつかのsutbleエラーをチェックできます。検出されたエラーのいずれかが、バグの原因である可能性があります。これらのツールに関するいくつかの情報はここにあります。

于 2012-10-03T16:33:46.840 に答える