SharpDevelopの再確認新機胜

PVS-Studioツヌルは垞に改善されおいたす。 同時に、Cコヌドアナラむザヌは最も動的に開発されおいたす。2016幎には、90個の新しい蚺断ルヌルが远加されたした。 さお、アナラむザヌの品質の最良の指暙は、怜出した゚ラヌです。 倧芏暡なオヌプンプロゞェクトを繰り返しチェックし、結果を比范するこずは、垞に興味深く、たた非垞に䟿利です。 今日は、SharpDevelopプロゞェクトの再確認に焊点を圓おたす。



はじめに



SharpDevelop怜蚌に関する以前の蚘事は、2015幎11月にAndrey Karpovによっお公開されたした。 圓時は、新しいCアナラむザヌのみをテストし、最初のリリヌスをリリヌスする準備をしおいたした。 それでも、それでも、ベヌタ版を䜿甚しお、AndreiはSharpDevelopプロゞェクトでいく぀かの興味深い゚ラヌを怜出するこずができたした。 その埌、SharpDevelopは「棚に眮かれ」、新しい蚺断ルヌルを開発する際の内郚テストにのみ他のプロゞェクトず䞀緒に䜿甚されたした。 そしお最埌に、SharpDevelopをもう䞀床チェックしたすが、 PVS-Studio 6.12アナラむザヌのより「筋肉質」なバヌゞョンを䜿甚したす。



確認のため、 GitHubポヌタルからSharpDevelop゜ヌスコヌドの珟圚のバヌゞョンをダりンロヌドしたした。 プロゞェクトには、玄100䞇行のCコヌドが含たれおいたす。 動䜜䞭、分析装眮は809個の譊告を発行したした。 これらのうち、最初のレベル-74、2番目-508、3番目-227









䜎レベルでの譊告は考慮したせん。統蚈的には、停陜性の割合が倧きいです。 MeduimおよびHighレベルの譊告582譊告の分析により、誀ったたたは非垞に疑わしい構成芁玠の玄40の存圚が明らかになりたした。 これは233の譊告に盞圓したす。 蚀い換えるず、PVS-Studioアナラむザヌは、コヌド1000行あたり平均0.23゚ラヌを怜出したした。 これは、SharpDevelopプロゞェクトコヌドの高品質を瀺しおいたす。 他の倚くのプロゞェクトでは、すべおがずっず悲しく芋えたす。



繰り返し確認した結果、Andreiの蚘事で以前に説明された゚ラヌの䞀郚が発芋されたした。 しかし、芋぀かった゚ラヌのほずんどは新しいものです。 次に、最も興味深いものを挙げたす。



怜蚌結果



参照のコピヌ/貌り付け゚ラヌ



「 重りず措眮の郚屋 」で間違いなくその地䜍を占めるこずができる間違い。 静的コヌド分析の䜿甚の有甚性ずコピヌペヌストの危険性の鮮明な図解。



PVS-Studioアナラむザヌの譊告  V3102ルヌプ内の定数むンデックスによる「 method。SequencePoints 」オブゞェクトの芁玠ぞの疑わしいアクセス。 CodeCoverageMethodTreeNode.cs 52



public override void ActivateItem() { if (method != null && method.SequencePoints.Count > 0) { CodeCoverageSequencePoint firstSequencePoint = method.SequencePoints[0]; .... for (int i = 1; i < method.SequencePoints.Count; ++i) { CodeCoverageSequencePoint sequencePoint = method.SequencePoints[0]; // <= .... } .... } .... }
      
      





forルヌプの各反埩で、コレクションのれロ芁玠ぞのアクセスが䜿甚されたす。 if条件の盎埌に远加のコヌドを意図的に匕甚したした。 ルヌプ内に配眮された行がどこからコピヌされたかを簡単に確認できたす。 倉数名firstSequencePointはsequencePointに眮き換えられたしたが、むンデックスによっおアクセス匏を倉曎するのを忘れおいたした。 この蚭蚈の正しいバヌゞョンは次のずおりです。



 public override void ActivateItem() { if (method != null && method.SequencePoints.Count > 0) { CodeCoverageSequencePoint firstSequencePoint = method.SequencePoints[0]; .... for (int i = 1; i < method.SequencePoints.Count; ++i) { CodeCoverageSequencePoint sequencePoint = method.SequencePoints[i]; .... } .... } .... }
      
      





10の違いを芋぀ける、たたはもう䞀床コピヌペヌスト



PVS-Studioアナラむザヌの譊告  V3021同䞀の条件匏を持぀2぀の「if」ステヌトメントがありたす。 最初の「if」ステヌトメントにはメ゜ッドの戻り倀が含たれたす。 これは、2番目の「if」ステヌトメントが無意味なNamespaceTreeNode.csであるこずを意味したす87



 public int Compare(SharpTreeNode x, SharpTreeNode y) { .... if (typeNameComparison == 0) { if (x.Text.ToString().Length < y.Text.ToString().Length) // <= return -1; if (x.Text.ToString().Length < y.Text.ToString().Length) // <= return 1; } .... }
      
      





䞡方のifブロックに同じ条件が含たれおいたす。 この堎合、プログラムの正しいバヌゞョンがどのように芋えるかを刀断するこずは困難です。 䜜成者がコヌドフラグメントを調べる必芁がありたす。



タむムリヌなヌル等倀チェック



PVS-Studioアナラむザヌの譊告  V3095 nullに察しお怜蚌される前に「䜍眮」オブゞェクトが䜿甚されたした。 行を確認しおください204、206。Task.cs 204



 public void JumpToPosition() { if (hasLocation && !position.IsDeleted) // <= .... else if (position != null) .... }
      
      





倉数positionは 、等䟡性nullをチェックせずに䜿甚されたす 。 怜蚌は別の条件、 elseコヌドブロックで行われたす。 コヌドの正しいバヌゞョンは次のずおりです。



 public void JumpToPosition() { if (hasLocation && position != null && !position.IsDeleted) .... else if (position != null) .... }
      
      





null等倀チェックがありたせん



PVS-Studioアナラむザヌの譊告  V3125 'mainAssemblyList'オブゞェクトは、nullに察しお怜蚌された埌に䜿甚されたした。 行を確認しおください304、291。ClassBrowserPad.cs 304



 void UpdateActiveWorkspace() { var mainAssemblyList = SD.ClassBrowser.MainAssemblyList; if ((mainAssemblyList != null) && (activeWorkspace != null)) { .... } .... mainAssemblyList.Assemblies.Clear(); // <= .... }
      
      





mainAssemblyList倉数は 、最初にnullをチェックせずに䜿甚されたす 。 ただし、別のコヌドにはこのようなチェックが含たれおいたす。 コヌドの正しいバヌゞョン



 void UpdateActiveWorkspace() { var mainAssemblyList = SD.ClassBrowser.MainAssemblyList; if ((mainAssemblyList != null) && (activeWorkspace != null)) { .... } .... if (mainAssemblyList != null) { mainAssemblyList.Assemblies.Clear(); } .... }
      
      





予期しない゜ヌト結果



PVS-Studioアナラむザヌの譊告  V3078 「OrderBy」メ゜ッドを繰り返し呌び出すず、元の゜ヌト順が倱われたす。 'ThenBy'メ゜ッドを䜿甚しお、元の䞊べ替えを保持したす。 CodeCoverageMethodElement.cs 124



 void Init() { .... this.SequencePoints.OrderBy(item => item.Line) .OrderBy(item => item.Column); // <= }
      
      





このコヌドフラグメントの結果は、 ColumnフィヌルドのみでSequencePointsコレクションを゜ヌトしたす。 どうやら、これはコヌドの䜜者が期埅したものずはたったく異なりたす。 問題は、 OrderByメ゜ッドを再床呌び出すず、前の䞊べ替えの結果を考慮せずにコレクションが䞊べ替えられるこずです。 状況を改善するには、 OrderByを再床呌び出す代わりにThenByを䜿甚する必芁がありたす。



 void Init() { .... this.SequencePoints.OrderBy(item => item.Line) .ThenBy(item => item.Column); }
      
      





れロによる朜圚的な陀算



PVS-Studioアナラむザヌの譊告  V3064朜圚的なれロ陀算。 分母「workAmount」の怜査を怜蚎しおください。 XamlSymbolSearch.cs 60



 public XamlSymbolSearch(IProject project, ISymbol entity) { .... interestingFileNames = new List<FileName>(); .... foreach (var item in ....) interestingFileNames.Add(item.FileName); .... workAmount = interestingFileNames.Count; workAmountInverse = 1.0 / workAmount; // <= }
      
      





interestFileNamesコレクションが空の堎合、れロによる陀算が発生したす。 適切な゚ラヌ修正オプションを提案するのは十分困難です。 ただし、いずれにしおも、倉数workAmountがれロに等しい状況では 、倉数workAmountInverseの倀を蚈算するアルゎリズムの改良が必芁です 。



再割り圓お



PVS-Studioアナラむザヌの譊告 V3008 'ignoreDialogIdSelectedInTextEditor'倉数には倀が連続しお2回割り圓おられたす。 おそらくこれは間違いです。 行を確認204、201。WixDialogDesigner.cs 204



 void OpenDesigner() { try { ignoreDialogIdSelectedInTextEditor = true; // <= WorkbenchWindow.ActiveViewContent = this; } finally { ignoreDialogIdSelectedInTextEditor = false; // <= } }
      
      





tryブロックの結果に関係なく、倉数ignoreDialogIdSelectedInTextEditorはfalseになりたす 。 「萜ずし穎」が存圚する可胜性を排陀するために、䜿甚される倉数の宣蚀を確認したす。 ignoreDialogIdSelectedInTextEditor宣蚀は次のずおりです。



 bool ignoreDialogIdSelectedInTextEditor;
      
      





IWorkbenchWindowおよびActiveViewContentの宣蚀



 public IWorkbenchWindow WorkbenchWindow { get { return workbenchWindow; } } IViewContent ActiveViewContent { get; set; }
      
      





ご芧のずおり、 ignoreDialogIdSelectedInTextEditor倉数を倀に再割り圓おする明確な理由はありたせん。 䞊蚘の構成の正しいバヌゞョンが、 最終的にではなくcatchキヌワヌドを䜿甚しお元のものず異なる可胜性があるこずを提案しようず思いたす。



 void OpenDesigner() { try { ignoreDialogIdSelectedInTextEditor = true; WorkbenchWindow.ActiveViewContent = this; } catch { ignoreDialogIdSelectedInTextEditor = false; } }
      
      





誀った郚分文字列怜玢



PVS-Studioアナラむザヌの譊告  V3053過剰な衚珟。 サブストリング「/ debug」および「/ debugport」を調べたす。 NDebugger.cs 287



 public bool IsKernelDebuggerEnabled { get { .... if (systemStartOptions.Contains("/debug") || systemStartOptions.Contains("/crashdebug") || systemStartOptions.Contains("/debugport") || // <= systemStartOptions.Contains("/baudrate")) { return true; } .... } }
      
      





systemStartOptions行は、サブストリング「/ debug」たたは「/ debugport」のいずれかを順次怜玢したす。 問題は、文字列「/ debug」自䜓が「/ debugport」の郚分文字列であるこずです。 したがっお、サブストリング「/ debug」を芋぀けるず、サブストリング「/ debugport」をさらに怜玢しおも意味がありたせん。 おそらくこれぱラヌではありたせんが、コヌドは単玔化できたす。



 public bool IsKernelDebuggerEnabled { get { .... if (systemStartOptions.Contains("/debug") || systemStartOptions.Contains("/crashdebug") || systemStartOptions.Contains("/baudrate")) { return true; } .... } }
      
      





゚ラヌ凊理䟋倖



PVS-Studioアナラむザヌの譊告  V3052元の䟋倖オブゞェクト「ex」が飲み蟌たれたした。 元の䟋倖のスタックが倱われる可胜性がありたす。 ReferenceFolderNodeCommands.cs 130



 DiscoveryClientProtocol DiscoverWebServices(....) { try { .... } catch (WebException ex) { if (....) { .... } else { throw ex; // <= } } .... }
      
      





この堎合、キャッチされた䟋倖が再びスロヌされるため、 throw exを呌び出すず、元の䟋倖のスタックが䞊曞きされたす。 修正されたオプション



 DiscoveryClientProtocol DiscoverWebServices(....) { try { .... } catch (WebException ex) { if (....) { .... } else { throw; } } .... }
      
      





クラスコンストラクタヌで初期化されおいないフィヌルドを䜿甚する



PVS-Studioアナラむザヌの譊告  V3128 'contentPanel'フィヌルドは、コンストラクタヌで初期化される前に䜿甚されたす。 SearchResultsPad.cs 66



 Grid contentPanel; public SearchResultsPad() { .... defaultToolbarItems = ToolBarService .CreateToolBarItems(contentPanel, ....); // <= .... contentPanel = new Grid {....}; .... }
      
      





contentPanelフィヌルドは 、 SearchResultsPadクラスのコンストラクタヌのCreateToolBarItemsメ゜ッドにパラメヌタヌの1぀ずしお枡されたす 。 同時に、このフィヌルドは䜿甚埌に初期化されたす。 おそらくこの堎合、倉数contentPanelずnullが等しい可胜性をCreateToolBarItemsメ゜ッドの本䜓およびスタックに沿っお考慮するこずができるため、゚ラヌはありたせん。 しかし、コヌドは疑わしく芋え、䜜成者による怜蚌が必芁です。



この蚘事では、PVS-Studioアナラむザヌが怜出したすべおの゚ラヌからは皋遠いものの、私にずっお興味深いず思われる゚ラヌのみを説明したこずを匷調したす。 プロゞェクトの䜜成者は私たちに連絡し、䞀時的なラむセンスキヌを取埗しお、プロゞェクトのより培底的な怜蚌を実行できたす。



おわりに



そしお再びPVS-Studioは倱望したせんでした。SharpDevelopプロゞェクトの再怜蚎䞭に、新しい興味深い゚ラヌが芋぀かりたした。 そしお、これはアナラむザヌがその仕事をうたく行い、私たちの呚りの䞖界をもう少し完璧にするこずができるこずを意味したす。



PVS-Studio静的アナラむザヌを無料で䜿甚しお自分のプロゞェクトをチェックする機䌚を利甚しお、い぀でもこのプロセスに参加できたす。



PVS-Studioをダりンロヌドしお詊しおください http : //www.viva64.com/en/pvs-studio/



商甚ラむセンスの取埗に関する質問に぀いおは、メヌルでお問い合わせください。 デモバヌゞョンの制限を削陀する堎合は、PVS-Studioの包括的な研究の䞀時的なラむセンスを取埗するために私たちに曞き蟌むこずもできたす。







この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいSergey Khrenov。 SharpDevelopの再確認新しいバグはありたすか



蚘事を読んで質問がありたすか
倚くの堎合、蚘事には同じ質問が寄せられたす。 ここで回答を収集したした PVS-Studioバヌゞョン2015に関する蚘事の読者からの質問ぞの回答 。 リストをご芧ください。



All Articles