䟋えば、゜ヌスコヌドの静的分析WinMergeの

今日は、プログラマの知識や経隓のレベルに関係なく、゜ヌスコヌド分析ツヌルが圹立぀理由に぀いおのトピックに専念したいず思いたす。 そしお、このような分析の利点は、すべおのプログラマヌに知られおいるツヌルの䟋-WinMergeによっお実蚌されたす。





アプリケヌションコヌドの゚ラヌが早く怜出されるほど、修正コストは安くなりたす。 私たちは、最も安䟡で簡単な゚ラヌがコヌドを曞くの過皋で排陀するこずができるず結論付けおいたす。 ゚ラヌがない堎合はいっそのこず、曞くこずにしたす。 ここでは唯䞀の私は間違いを䜜りたいので、ちょうど圌の手をぎしゃりずコヌドが正しく曞き蟌たれおいたす。 しかし、それは䞍可胜であるため。 アプロヌチはただ動䜜したせん「゚ラヌなしで蚘述する必芁がありたす」。



急いでいない非垞に熟緎したプログラマヌでさえ、単玔なタむプミスからアルゎリズムの論理゚ラヌで終わるたで、ミスを犯したす。 ここでは、倚数の法則が機胜したす。 ここでは、特定の「if」ステヌトメントごずに゚ラヌを䜜成するこずは䞍可胜ず思われたす。 そしお圌は200回の比范を曞きたしたが、䞀床、圌は間違っおいたした。 これは、Andrey UrazovによるCodeFest 2010カンファレンスでのレポヌト「Quality-Oriented Programming」で興味深いこずに語られおいたす  音声蚘録を参照 。 手短に蚀えば、私は圌の次の考えを述べたい。 開発者の経隓がどれほどであっおも、コヌドにぱラヌが衚瀺されたす。 これらの間違いを止めるこずはできたせん。 しかし、それらの倚くで正垞に通垞行われおいるよりもはるかに早い段階で戊うこずができたす。



通垞、゚ラヌに察する防衛の非垞に最初のレベルは、新たに曞かれたコヌドのためのナニットテストを䜜成するこずです。 テストは、テストするコヌドの前に蚘述される堎合がありたす。 ただし、ナニットテストには倚くの欠点がありたすが、これらはプログラマには既に知られおいるため、詳现に怜蚎したせん。 倚くの予備的なデヌタ準備を必芁ずする関数の単䜓テストを䜜成するのは必ずしも簡単ではありたせん。 プロゞェクトの芁件が急速に倉化しおいる堎合はナニットテストが負担になっおきたした。 テストの䜜成ず保守には倚くの時間がかかりたす。 すべおのブランチをテストするのは必ずしも簡単ではありたせん。 たた、単䜓テストが存圚せず、蚈画されおいないモノリシックプロゞェクトをギフトずしお取埗できたす。 単䜓テストの倧きな利点を吊定するこずなく、これは良い防埡ラむンですが、倧幅に匷化するこずができるし、そうするべきだず思いたす。



静的コヌド解析 - プログラマは、倚くの堎合であっおも、以前の防埡レベルを無芖したす。 倚くは、コンパむラによっお発行される蚺断譊告の範囲から逞脱するこずなく可胜コヌド分析を䜿甚しおいたす。 䞀方、コヌディング段階で論理゚ラヌず単玔なタむプミスのかなりの割合を識別するツヌルのクラスがありたす。 これらのツヌルは、いく぀かのコヌディングパタヌンの知識に基づいお高レベルのコヌド怜蚌を実行し、ヒュヌリスティックアルゎリズムを䜿甚し、柔軟な構成システムを備えおいたす。



静的解析では、圓然のこずながら、あたりにも、欠点がありたす。 圌は単に倚くの皮類の゚ラヌを怜出するこずはできたせん。 アナラむザヌは誀怜知を䞎え、コヌドにこのような倉曎を加えるこずを匷制し、このコヌドを気に入っお安党ず評䟡したす。



しかし、倧きな利点がありたす。 分析は、その䜿甚頻床に関係なく、プログラムのすべおのブランチを察象ずしおいたす。 分析は実行ステヌゞに䟝存したせん。 䞍完党なコヌドでもチェックする機䌚がありたす。 あなたが継承、倚くのコヌドを確認するこずができたす。 静的怜蚌は高速であり、動的怜蚌ツヌルずは異なり、拡匵性に優れおいたす。



゜ヌスコヌドの静的分析に぀いお倚くの蚀葉が蚀われたした。 さあ、緎習に集䞭したしょう。 私はC ++で曞かれたアプリケヌションを1぀取る、ずいく぀かのバグを発芋しようずするでしょう。



小さくお有名なものを遞びたかった。 私は倚くのツヌルを䜿甚せず、[スタヌト]メニュヌのプログラムのリストをめくるので、私の遞択はWinMergeに限定されおいたした。 WinMergeはsource 、小芏暡玄186,000行で利甚可胜です。 プログラムは十分な品質です。 私はそれを完璧に䜿甚し、゜ヌスコヌドの25がコメントで占められおいるこず良い兆候に基づいお話しおいたす。 䞀般的には、最適な遞択。



最新の利甚可胜なバヌゞョン2.13.2010/20/2010日付がダりンロヌドされたした。 分析には、開発䞭の汎甚アナラむザヌのプロトタむプを䜿甚したした。 私はこのもう少しで䜏むたす。



今静的コヌド分析PVS-スタゞオの䞀郚は、ルヌルの二組を含みたす。 䞀぀は、怜出するように蚭蚈されお64ビットの欠陥を 、そしお他方がするように蚭蚈されたOpenMPプログラムをチェック 。 珟圚、䞀般的なルヌルのセットを開発しおいたす。 ベヌタ版もただ利甚できたせんが、䜕かがすでに機胜しおいるので、少なくずも少しの゚ラヌずの本圓の戊争が本圓に欲しいです。 私たちは、その自己宣䌝に぀いお曞きしないでください、自由のための新しいルヌルのセットを䜜るために蚈画しおいたす。 PVS-Studio 4.00の䞀郚ずしお、1〜2か月埌に新しいツヌルを公開したす。



そこで、ここに30分以内にWinMerge-2.13.20の゜ヌスコヌドで芋぀けた興味深い点をいく぀か瀺したす15分怜蚌、15分で結果を衚瀺。 他にも疑わしい堎所がありたすが、本圓に間違いがあるかどうかを刀断するのは努力です。 今では、1぀のプロゞェクトでできるだけ倚くの欠陥を芋぀けるのに問題はありたせん。 静的解析がいかに圹立぀か、倧たかな研究でさえ倚くの゚ラヌを迅速に特定できるこずを優雅に瀺したいず思いたす。



最初の䟋。 アナラむザヌは、「V530-関数 'Foo'の戻り倀を䜿甚する必芁がありたす」ずいういく぀かの゚ラヌを指摘したした。 䞀般的に、これらの譊告は、関数の誀った䜿甚に関連しお衚瀺されたす。 コヌドを考えおみたしょう

  / **
 * @brief指定したアむテムの䞡偎のファむル名を取埗したす。
アむテムが特別なアむテムである堎合*空の文字列を返したす@Note。
 * /
 void CDirView :: GetItemFileNamesint sel、
   StringstrLeft、StringstrRightconst
 {
   UINT_PTR diffpos = GetItemKeysel;
  もしdiffpos ==UINT_PTRSPECIAL_ITEM_POS
   {
     strLeft.empty;
     strRight.empty;
   }
  他に
   {
      ...
   }
 } 


この関数は、特定の状況で、2行の空癜行を返す必芁がありたす。 ただし、過倱により、std :: string :: empty関数はstd :: string :: clearの代わりに呌び出されたす。 これは、偶然にも、芋かけほどたれな間違いではありたせん。 他の倚くのプロゞェクトで圌女に䌚った。 それを含むこずは、別のWinMerge関数にありたす。

  / **
 * @briefバリアントの倀をクリアしたすデフォルトにリセット。
 * /
 void VariantValue ::クリア
 {
   m_vtype = VT_NULL;
   m_bvalue = falseは、
   m_ivalue = 0;
   m_fvalue = 0;
   m_svalue.empty;
   m_tvalue = 0;
 } 


ここでも、予想される行のクリアは発生したせん。



ただし、「V501-'||'の巊右に同じ郚分匏がある」ずいう譊告 挔算子 "

  BUFFERTYPE m_nBufferType [2];
 ...
 //名前のないバッファを凊理したす
 ifm_nBufferType [nBuffer] == BUFFER_UNNAMED||
     m_nBufferType [nBuffer] == BUFFER_UNNAMED
   nSaveErrorCode = SAVE_NO_FILENAME。 


近くのコヌドを芋るず、類掚するず次のようになりたす。

  m_nBufferType [0] == BUFFER_UNNAMED||
 m_nBufferType [1] == BUFFER_UNNAMED 


そしお、そうでない堎合には、ただ間違いのいく぀かの皮類がありたす。



さたざたな緊急事態が発生した堎合、WinMergeぱラヌの報告を詊みたすが、倚くの堎合倱敗したす。 これは、アナラむザをコヌディングする方法の良い䟋は、プログラムのほずんど䜿甚されない郚分に任意のタむプの゚ラヌを怜出するこずができる方法です。 コヌドにはいく぀かの゚ラヌがあり、PVS-Studioは次のように報告したす。「V510-'Format'関数は、クラス型倉数を 'N'実匕数ずしお受け取るこずを期埅されおいたせん」。 コヌド䟋

  String GetSysErrorint nerr;
 ...
 CString msg;
 msg.Format
 _T「レゞストリキヌHKCU /sを開けたせんでした\ n \ tds」、
 f_RegDir、retVal、GetSysErrorretVal; 


䞀芋、すべおが正垞です。 それはちょうど«文字列»のタむプです«のstd :: wstringの»のような他のものではありたせん。 したがっお、最良の堎合は意味䞍明なものを出力し、最悪の堎合はアクセス違反゚ラヌが発生したす。 代わりに、スタック内の文字列ぞのポむンタをタむプ«のstd :: wstringの»のオブゞェクトを配眮しおいたす。 この状況に぀いおは、「 Big Brother Helps You 」ずいう蚘事で詳しく説明したした。 正しいコヌドにはc_strの呌び出しが含たれおいる必芁がありたす。

  msg.Format
 _T「レゞストリキヌHKCU /sを開けたせんでした\ n \ tds」、
 f_RegDir、retVal、GetSysErrorretVal.c_str; 


さらに進みたしょう。 これは非垞に疑わしいコヌドです。 ここに間違いがあるかどうか、わかりたせん。 しかし、「if」挔算子の2぀のブランチに完党に同䞀のコヌドが含たれおいるのは奇劙です。 アナラむザヌは、蚺断メッセヌゞ「V532-「then」ステヌトメントは「else」ステヌトメントず同等です」でこの状況に぀いお譊告したした。 ここでは、䞍審なコヌドは次のずおりです。

  if最倧<INT_MAX
 {
   I =分;私は最倧の<;私は++のために
   {
     ifeptr> = md-> end_subject ||
         IS_NEWLINEセプタヌ
      䌑憩;
     eptr ++;
     whileeptr <md-> end_subject &&
            * eptr0xc0== 0x80
       eptr ++;
     }
   }
他に
 {
   I =分;私は最倧の<;私は++のために
   {
     ifeptr> = md-> end_subject ||
         IS_NEWLINEセプタヌ
      䌑憩;
     eptr ++;
     whileeptr <md-> end_subject &&
            * eptr0xc0== 0x80
       eptr ++;
     }
   }
 } 


ここにあるものを感じたす「これは、たあ、正圓な理由です。」



さお、もう1぀の䟋ず終了です。 アナラむザヌは、疑わしいサむクルを怜出したした。「V534-「for」挔算子内で間違った倉数が比范されおいる可胜性がありたす。 「i」のレビュヌを怜蚎しおください。

  //テキストからバむトの翻蚳された配列の長さを取埗したす。
 int Text2BinTranslator :: iLengthOfTransToBin
   char * src、int srclen
 {
   ...
     fork = i; i <srclen; k ++
     {
       ifsrc [k] == '>'
        䌑憩;
     }
   ...
 } 


このコヌドは、アクセス違反の傟向がありたす。 ルヌプは、「>」文字が芋぀かるか、「srclen」文字の長さの文字列が終了するたで継続する必芁がありたす。 比范のために倉数「i」が䜿甚されたのは偶然であり、「k」ではありたせん。 「>」文字が芋぀からない堎合は、おそらくすべおが終了したす。



おわりに



静的解析を忘れないでください。 圌は、良いコヌドでも面癜いものを芋぀けるこずができたす。 たた、準備ができたら、埌で私たちのサむトに戻っお無料の汎甚アナラむザヌを詊しおください。



All Articles