2012-10-03 10 views
14

軽く書くために、私は小さなメモリの問題があり、原因を特定するためのツールやアイデアが不足しています。スタックを分離するためのツール

私は高度なマルチスレッド(pthreads)C/C++プログラムを持っています。このプログラムは、4.4.4以降、4.7.1より前のGCCで最適化されたコンパイルでスタック・スマッシングの問題を発生させました。

症状は、スレッドの作成中に、%RIPだけでなく、すべての親フレームと、ほとんどのレジスタが0x00または他の非センスアドレスであることです。 問題を引き起こすスレッドは一見無作為ですが、ログメッセージで判断すると同じHunkのコードに分かれているように見えますが、新しいスレッドの作成時には半反復可能なポイントになるようです。

これは、違反しているファイル内のprint()がこれまでのところ、コンパイル単位が1000行の単一のコンパイル単位より狭くトラップして分離するのを難しくしましたアクティブなセクションを下に移動します。

最終的にスタックスマッシュスレッドをオフリードスレッドの作成は、次のとおりです。


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以上、最適化ビルドにのみ存在します。

Aは、-O2 -Wstack-プロテクタが間違って何も見ないでコンパイルし を私はValgrindの/ memcheckやDRDを試してみましたが、両方のスタックが吹き飛ばさ(と失敗に到達するために12時間の程度かかります)される前に、すべての問題を見つけることができませんしかし、-fstack-protector-allでビルドするとバグから私を守りますが、エラーは発生しません。

エレクトリックフェンスもトラップしますが、スタックがなくなった後のみです。

質問:問題のあるセクションを絞り込むのに役立つツールやテクニックは他にありますか?

多くのおかげで、 --Bill

+0

OK。私は噛むだろう...どのスタックは壊される? –

+1

作成スレッドのスタックであれば、いくつかのコードがうまくいくかもしれません - 新しいスレッドに何を渡すのですか? –

+2

明確にするために、g ++ 4.4.2と4.8で正常に動作しているとか、それらのバージョンがテストされていないと言っていますか? –

答えて

4

この種の問題にアプローチするためのオプションのカップル:

あなたは、破損が発生する前に、スタックのアドレスにハードウェアブレークポイントを設定してみてくださいと漠然と便利なデバッグを提供するために、腐敗の早い段階で十分なデバッガのブレークを願っています可能性があり状態。ここの難しい部分は、の右のスタックアドレスを選択することです。問題のスレッドの「選択」がどのくらいランダムであるかによっては、これは実用的ではないかもしれません。しかし、あなたのコメントの1つでは、新しく作成されたスレッドが壊れているように聞こえるので、これは実行可能かもしれません。スレッドの作成中に中断し、スレッドのスタック位置を把握し、いくつかの野生の推測で相殺し、ハードウェアBPを設定して、続行してください。あまりにも早すぎる、遅すぎる、遅くなる、遅くなる、遅くする、遅くする、遅くする、遅くする、遅くする、遅くする、遅くする、これは、基本的には高度な推測とチェックであり、破損パターンがランダムすぎる場合、重大な妨げになる可能性がありますが、半読み可能なスタックと成功したデバッグ努力につながる可能性があります。

もう1つの方法は、クラッシュダンプの収集を開始することです。クラッシュダンプの間のパターンを探して、破損の原因に近づけるのに役立つかもしれません。おそらくあなたは幸運になり、クラッシュダンプの1つが「より速く」/「ソースに近い」クラッシュするでしょう。

残念なことに、これらの技術はいずれも科学技術であり、彼らは非決定論的であり、健康的な運勢に頼っています(少なくとも私の経験では、クラッシュダンプで素晴らしいことをすることができる人がいると言われていますが、時間がかかりますそのスキルのレベルに達するために)。

もう1つの注意点として、初期化されていないメモリは、デバッグとリリースの違いの非常に典型的なソースであり、ここでは簡単に問題になる可能性があります。しかし、タイミングの違いがあることに留意する別の可能性があります。スレッドがスケジュールされる順序と期間は、デバッグとリリースではしばしば劇的に異なり、一方では同期バグがマスクされますが、もう一方ではマスクされません。これらの違いは実行速度の違いによるものかもしれませんが、デバッグ環境でスレッドスケジューリングを意図的に混乱させるランタイムがあると思います。

+0

ありがとうございましたあなたの回答と入力のためにすべて私は答えとしてこれを受け入れていますが、私はこのバグを分離しようとしているので、より多くのアイデアや考えがあれば、より多くの入力を歓迎します。 –

+0

私は言及を忘れてしまったが、コードベースが許すならば、これらの種類の問題に役立つ別のトリック:スレッドの最大数を変更する。バグを確実に再現するために必要な同時スレッドの数を最小限に抑えると、一般的には、より親和性のあるデバッグ環境につながります。理想的には、2つのスレッドに渡すことができます(または、あるスレッドでreprosを見つけて、実際にはシンクロバグではなく、常にこれを排除するのが得策です)。 – WeirdlyCheezy

2

あなたは多分発見されたエラーのいずれかがあなたのバグの原因となる、いくつかのsutbleエラーをチェックするために静的解析ツールを使用することができます。これらのツールに関する情報はhereです。

+0

良い点、私はこれを見つけることを試みるためにLint等を考慮しなかった。 –

関連する問題