(8)並列処理問題をソースから見つけるためのヒント [ 並列処理の不具合と対策 ]

これまでのブログであげた並列処理問題の解決方法を考えてみます

n並列処理動作の問題は超レアケースで再現性なし

 

ライブロック・デッドロック、リエントラントの問題など、並列処理で発生する多くのものはある条件下で発生し、その条件は絶妙のタイミングで起きることが多いです。

一度発生しても、再度確認すると発生しないことも多く、調査や確認することがとても難しいものです。

 

特定条件下でタイミングよく別の処理が動作する
ひとつのミューテックス変数を確保した時に、もう一つの変数を別スレッドが確保する
printfを書いたら動いてしまう
デバッガを使うと動いてしまうこともある
まれに止まる
まれに遅くなる

 

プログラムを動かせば必ず発生するような簡単な問題でないことが多く、全く別の処理との関連で発生するような不具合の場合、狭いソースプログラム範囲内で問題を検出する単体テストなどで見つけることはできません。

また、プログラムを長時間動かした結果、微妙なタイミングが偶然発生して現れる不具合に遭遇する可能性は高くないでしょう。

n動的テストが難しいなら、静的解析が使えるか

 

ソースプログラム全体を見渡して問題を検出してくれる静的解析ツールは様々な情報を提供してくれます。

ツールにより得意なゾーンに違いがあるので、ここに示す情報をすべて提供してくれるわけではありませんが、様々な情報が得られます。

 

コーディングルール違反

文法的に正しくても、プログラム作成者の意図と異なる動作をする可能性のある記述や誤認識しそうな記述を禁止するコーディングルール。

MISRAAUTOSARCERTESCR(IPA/SEC)、 ...

 

一般的な解析情報

コンパイラによっては警告を発するような比較的簡単に判定可能な記述誤り等の指摘。

NULLポインタの間接参照、リソースリーク、不適切/不正な記述、チェック前のNULLポインタ使用、非初期化変数参照、領域解放後の参照、配列オーバーラン(アンダーラン)、型や領域割り当てのミスマッチ、動的アロック域の領域外参照、負の値の未チェック使用、ローカル変数アドレスの誤使用、リターン記述漏れ、関数戻り値の無視、型変換(負値のunsigned)、関数のキャスト、 ...

 

意味論的分析情報

動かさず、しかしシミュレートするようにプログラムの文脈を捜査し、より深く問題点を指摘。

未到達コード、配列外アクセス、ゼロ割、初期化漏れ、演算オーバーフロー/アンダーフロー、不定の戻り値、ビットサイズ以上や負のシフト、ポインタの誤り(アラインメント等)、関数や変数ポインタ値の誤り、非初期化ポインタ、終了しない関数呼び出し、無限ループ、絶対番地アクセス、共有変数、未使用変数、リードオンリー・ライトオンリー変数、多重書込み変数、未使用引数、前回値参照、再帰関数、リエントラント関数、制御フロー解析、データフロー解析、クロスリファレンス、差分(影響度分析)、コードクローン検出、ソース解析補助機能(関数・変数の定義と参照情報)、ソース解析補助機能(関数・変数の依存関係図)、メトリクス測定、凝集度、結合度、 ...

 

 

静的解析には限界もあり、不正確な指摘 (誤検知)をすることもありますが、それも含め指摘事項を再確認することはプログラムの完成度をあげるのに大変役立ちます。

n静的解析情報を並列処理問題に当てはめてみる

 

過去のブログで示した並列不具合の問題を見つけるために、静的解析ツールが見つけてくれる使えそうな情報を割り当ててみました。

この表は完全ではありませんが、このような表をもとにソースプログラムを見直すことで問題点を見つけることができると思います。すべての問題点を見つけだることはできなくても、並列処理の不具合を見つけるためのヒントになりそうです。

 

使える情報はもっと多いかもしれませんし、対象プログラムに合わせて必要な指摘事項をうまく集めることで、簡単には見つからない並列処理の不具合を見つけ出すことができると思います。