私たちの経営陣は最近、C++静的解析ツールを販売している何人かの人々と話をしています。もちろん、営業担当者は大量のバグを見つけると言っていますが、私は懐疑的です.
そのようなツールは現実の世界でどのように機能しますか? 彼らは本当のバグを見つけますか? それらは、より多くのジュニア プログラマーの学習に役立ちますか?
彼らは苦労する価値がありますか?
私たちの経営陣は最近、C++静的解析ツールを販売している何人かの人々と話をしています。もちろん、営業担当者は大量のバグを見つけると言っていますが、私は懐疑的です.
そのようなツールは現実の世界でどのように機能しますか? 彼らは本当のバグを見つけますか? それらは、より多くのジュニア プログラマーの学習に役立ちますか?
彼らは苦労する価値がありますか?
静的コード分析は、ほとんどの場合、価値があります。既存のコード ベースの問題は、すぐに使用できるようにするには、おそらくあまりにも多くのエラーが報告されることです。
私はかつて、コンパイラから 100,000 件以上の警告があったプロジェクトに取り組んでいました...そのコードベースで Lint ツールを実行しても意味がありません。
Lint ツールを「正しく」使用するということは、より良いプロセスを受け入れることを意味します (これは良いことです)。私が経験した最高の仕事の 1 つは、警告付きでコードをチェックインすることを許可されていない研究所で働いていたことです。
そうです、ツールはそれだけの価値があります...長期的には。短期的には、コンパイラの警告を最大にして、報告される内容を確認してください。コードが「クリーン」である場合は、今こそ lint ツールを検討するときです。コードに多くの警告がある場合は、優先順位を付けて修正します。コードに警告がまったくない (または少なくとも非常に少ない) 場合は、Lint ツールを調べます。
そのため、Lint ツールは貧弱なコード ベースには役立ちませんが、優れたコード ベースがあれば、それを維持するのに役立ちます。
編集:
100,000 以上の警告製品の場合、約 60 の Visual Studio プロジェクトに分割されました。各プロジェクトですべての警告が削除されたため、警告がエラーになるように変更されたため、クリーンアップされたプロジェクトに新しい警告が追加されなくなりました (または、同僚がチェックインした開発者に正当に怒鳴ることができました)最初にコンパイルせずにコードを書いてください:-)
いくつかの雇用主との私の経験では、C/C++ 用の Coverity Prevent は明らかに価値がありました。優れた開発者のコードにもいくつかのバグが見つかり、最悪の開発者のコードにも多くのバグが見つかりました。他の人はすでに技術的な側面をカバーしているので、政治的な問題に焦点を当てます。
まず、静的解析を最も必要とするコードを持つ開発者は、自発的にそれを使用する可能性が最も低くなります。ですから、理論的にも実践的にも、強力な経営陣の支援が必要になると思います。そうしないと、実際にバグを修正することなく、印象的な指標を生成するための単なるチェックリスト項目になってしまう可能性があります。静的分析ツールは誤検知を生成します。たとえば、欠陥のトリアージ、チェッカーの優先順位付け、設定の微調整などによって、彼らからの煩わしさを最小限に抑えるために誰かを専念させる必要があるでしょう。(商用ツールは、偽陽性を 2 回以上表示しないという点で非常に優れている必要があります。それだけで価格に見合う価値があるかもしれません。) 本物の欠陥でさえ、不快感を引き起こす可能性があります。これに関する私のアドバイスは、心配しないことです。たとえば、明らかに破壊的なバグは「マイナーです。
私の最大のアドバイスは、上記の私の最初の法則の帰結です: 最初に安価なショットを取り、最悪の開発者からの痛いほど明白なバグを見てください. これらのいくつかは、コンパイラの警告によって発見されることさえありますが、多くのバグは、コマンド ライン オプションによって抑制されている場合など、これらの亀裂をすり抜けてしまう可能性があります。本当にあからさまなバグは政治的に役立つ可能性があります。たとえば、最も面白い欠陥のトップ 10 リストは、慎重に使用すれば驚くほど心を集中させることができます。
数人が指摘しているように、ほとんどのアプリケーションで静的分析ツールをフルに実行すると、多くの警告が表示されます。警告の一部は誤検知であったり、悪用可能な欠陥につながらない可能性があります。これらのタイプのツールはノイズが多く、おそらく時間の無駄であるという認識につながるのは、その経験です。ただし、セキュリティ、信頼性、または正確性の問題につながる可能性のある実際の潜在的に危険な欠陥を強調する警告があり、多くのチームにとって、これらの問題は修正することが重要であり、テストで発見することはほぼ不可能です.
とはいえ、静的分析ツールは非常に役立ちますが、それらを既存のコードベースに適用するには少し戦略が必要です。ここにあなたを助けるかもしれないいくつかのヒントがあります..
1) 一度にすべてを有効にしないでください。最初の欠陥のセットを決定し、それらの分析を有効にして、コード ベース全体で修正します。
2) あるクラスの欠陥に対処するときは、開発チーム全体がその欠陥とは何か、なぜそれが重要なのか、その欠陥を防御するためのコーディング方法を理解できるようにします。
3) コードベースからそのクラスの欠陥を完全に取り除く作業を行います。
4) このクラスの問題が修正されたら、問題ゼロの状態を維持するためのメカニズムを導入します。幸いなことに、ベースラインにエラーがない場合は、エラーを再導入していないことを確認する方がはるかに簡単です。
それは役に立ちます。試用版を入手して、無視されていると思われるコードベースの一部で実行することをお勧めします。これらのツールは、多くの誤検知を生成します。これらをくぐり抜けると、近い将来、多くの悲しみを救うことができるバッファオーバーランが1つか2つ見つかる可能性があります。また、少なくとも2つまたは3つの種類(およびいくつかのOpenSourceのもの)を試してください。
私はそれらを使用しました-たとえば、PC-Lint、そして彼らはいくつかのものを見つけました。通常、これらは構成可能であり、xyzが実際には問題ではないと判断した場合は、「xyzについて気にしないでください」と伝えることができます。
ジュニアプログラマーが多くを学ぶのに役立つかどうかはわかりませんが、コードを強化するためのメカニズムとして使用できます。
私は、2番目のセットの(懐疑的でバグの調査)目と単体テストが、通常、より多くのバグキャッチが行われるのを見た場所であることに気づきました。
それらのツールは役に立ちます。lint は、C 開発者にとって優れたツールです。
しかし、私が持っている反論の 1 つは、それらがかなりの量のコードを記述した後に実行されるバッチ プロセスであり、大量のメッセージを生成する可能性があるということです。
より良いアプローチは、IDE にそのようなものを組み込み、作成中に問題を指摘してもらい、すぐに修正できるようにすることだと思います。そもそも、これらの問題をコード ベースに入れないでください。
これが、Java 用の FindBugs 静的分析ツールと IntelliJ の Inspector の違いです。私は後者を大いに好みます。
特にコード ベースが大きい場合は、大量の誤検知に対処する必要があるでしょう。
ほとんどの静的解析ツールは、「プロシージャ内解析」を使用して動作します。つまり、プログラム全体を考慮する「プログラム全体解析」とは対照的に、各プロシージャを個別に検討します。
「プログラム全体の分析」では、実際には実際には発生しないプログラムの多くのパスを考慮する必要があり、多くの場合、偽陽性の結果が生成される可能性があるため、通常は「プロシージャ内」分析を使用します。
手続き内分析は、単一の手続きに集中するだけで、これらの問題を解消します。ただし、機能させるには、通常、プロシージャの引数、戻り値の型、およびオブジェクト フィールドのメタデータを記述するために使用する「注釈言語」を導入する必要があります。C++ の場合、これらは通常、装飾するマクロを介して実装されます。注釈は、「このフィールドは決して null ではない」、「この文字列バッファはこの整数値によって保護されている」、「このフィールドには「background」というラベルの付いたスレッドのみがアクセスできる」などを記述します。
分析ツールは、提供された注釈を取得し、記述したコードが実際に注釈に準拠していることを確認します。たとえば、null 以外としてマークされているものに null を渡す可能性がある場合、エラーがフラグされます。
注釈がない場合、ツールは最悪の事態を想定する必要があるため、実際にはエラーではない多くのエラーが報告されます。
このようなツールをまだ使用していないように見えるので、最初に報告されるすべての誤検知を取り除くために、コードに注釈を付けるのにかなりの時間を費やす必要があると想定する必要があります。最初にツールを実行し、エラーの数を数えます。これにより、コード ベースに採用するのに必要な時間を見積もることができます。
ツールに価値があるかどうかは、組織によって異なります。あなたが最も噛まれているバグの種類は何ですか? それらはバッファオーバーランのバグですか? それらは null 逆参照またはメモリ リークのバグですか? それらはスレッドの問題ですか?それらは「おっと、そのシナリオを考慮していませんでした」または「リトアニア版の Windows 98 で動作する製品の中国語版をテストしていませんでした」ということですか?
問題が何であるかを理解したら、努力する価値があるかどうかを知る必要があります。
このツールは、おそらくバッファ オーバーフロー、null 逆参照、およびメモリ リークのバグに役立ちます。「スレッドの色付け」、「効果」、または「許可」の分析をサポートしている場合、スレッドのバグに役立つ可能性があります。ただし、これらのタイプの分析はかなり最先端であり、膨大な表記上の負担があるため、いくらかの費用がかかります。このツールは、おそらく他の種類のバグには役に立ちません。
したがって、それは、作成するソフトウェアの種類と、最も頻繁に遭遇するバグの種類に大きく依存します。
適切なツールを使用している場合、静的コード分析は価値があると思います。最近、Coverity Tool (少し高価) を試しました。素晴らしいことに、lint や Purify では検出されなかった多くの重大な欠陥が発生しました。
また、Coverity を以前に使用していれば、顧客の現場での欠陥の 35% を回避できた可能性があることもわかりました。
現在、Coverity は私の会社で展開されており、古いソフトウェア バージョンで顧客の TR を取得するたびに、それに対して Coverity を実行して、サブシステムで分析を開始する前に、障害の可能性のある候補を引き出しています。
すべての場合と同様に、答えは異なります...おばあちゃんのために編み物パターンのきれいなプリンターに取り組んでいる唯一の開発者であれば、静的分析ツールを購入したくないでしょう。何か重要なことに取り組む中規模のソフトウェアプロジェクトがあり、それに加えてスケジュールが厳しい場合は、今少し投資して、後ではるかに節約できるようにすることをお勧めします。
私は最近これについて一般的な暴言を書いた:http://www.redlizards.com/blog/? p = 29
時間が許せばすぐにパート2を書く必要がありますが、一般的に、それがあなたにとって価値があるかどうか、いくつかの大まかな計算を行います。
私の個人的な見解も:
早い段階で静的分析を取得する
開発者に静的分析を自分で使用する機能を提供します
非常に高品質の無料ツールがある場合は、ほとんどの静的分析ツールにお金を払う必要はありません(商用バージョンで提供される非常に特別な機能や特定の機能が必要な場合を除く)。たとえば、cppcheckに関する別の質問で私が出したこの回答を参照してください。
あなたのプログラミングスタイルにかなり依存していると思います。主に C コード (たまに C++ 機能を使用) を書いている場合は、これらのツールが役立つ可能性があります (メモリ管理、バッファ オーバーランなど)。しかし、より洗練された C++ 機能を使用している場合、ソース コードを解析しようとするとツールが混乱する可能性があります (または、通常は C++ 機能の方が安全に使用できるため、多くの問題が検出されないだけです)。
このかなり驚くべき結果は、Elsa と Oink を使用して達成されました。
http://www.cs.berkeley.edu/~daw/papers/fmtstr-plas07.pdf
「Debian Linux におけるフォーマット文字列の脆弱性の大規模分析」Karl Chen、David Wagner、カリフォルニア大学バークレー校、{quarl, daw}@cs.berkeley.edu 著
概要:
フォーマット文字列のバグは、比較的一般的なセキュリティ上の脆弱性であり、任意のコードの実行につながる可能性があります。他社と協力して、汚染違反を検出できる静的分析手法である typequalifier 推論を使用して、Linux ディストリビューション全体からフォーマット文字列の脆弱性を排除するシステムを設計および実装しました。Debian 3.1 Linux ディストリビューションの C/C++ ソース パッケージの 66% を正常に解析しました。私たちのシステムは、1,533 のフォーマット文字列汚染警告を検出しました。これらの 85% は真陽性、つまり実際のバグであると推定されます。ライブラリからの重複を無視すると、約 75% が実際のバグです。フォーマット文字列の脆弱性を近い将来消滅させる技術が存在することをお勧めします。
カテゴリとサブジェクト記述子 D.4.6 [オペレーティング システム]: セキュリティと保護 - 侵略的ソフトウェア。一般条件: セキュリティ、言語。キーワード: フォーマット文字列の脆弱性、大規模解析、Typequalifier 推論
C++ であるかどうかに関係なく、実際のバグを見つける静的解析は価値があります。非常にノイズが多い傾向にあるものもありますが、符号付き/符号なしの比較などの微妙なバグを検出できる場合、最適化によってコードが壊れたり、範囲外の配列アクセスが発生したりする可能性がある場合は、間違いなく努力する価値があります。
以前の雇用主では、Insure++ を使用していました。Valgrind が見つけられなかったランダムな動作 (初期化されていないものの使用) を特定するのに役立ちました。しかし、最も重要なことは、まだエラーとして知られていない間違いを取り除くのに役立ちました.
Insure++ は優れていますが、価格が高いため、ユーザー ライセンスを 1 つだけ購入しました。