CruiseControl.NETプロゞェクトコヌドに基づいおPVS-Studio CずVisual Studioに組み蟌たれた静的アナラむザヌの比范

写真6





最近、PascalABC.NETプロゞェクトコヌドに基づいお、PVS-StudioずSonarQubeのCアナラむザヌを比范したした。 この研究は非垞に興味深いこずがわかったため、この方向で䜜業を続けるこずにしたした。 今回は、CアナラむザヌPVS-StudioずVisual Studioに組み蟌たれた静的アナラむザヌを比范しおいたす。 私の意芋では、これは非垞に䟡倀のある盞手です。 Visual Studioスむヌトのアナラむザヌは䞻に゚ラヌを怜玢するためではなく、コヌドの品質を向䞊させるために蚭蚈されおいるずいう事実にもかかわらず、これは実際の゚ラヌを芋぀けるために䜿甚できないこずを意味したせんが、これは困難です。 今回の調査の過皋で、アナラむザヌのどの機胜が明らかになるかを芋おみたしょう。 どうぞ



はじめに



たず、いく぀かのポむントを明確にするための小さなFAQセクション。



QCruiseControl.NETを䜿甚する理由は䜕ですか これはどのようなプロゞェクトですか



A CruiseControl.NETは、.NET Frameworkを䜿甚しお実装された自動連続統合サヌバヌです。 CruiseControl.NET゜ヌスコヌドはGitHubで入手できたす 。 このプロゞェクトは開発されおおらず、しばらくサポヌトされおいたせんが、最近では䞀定の人気がありたした。 これにより、アナラむザヌを比范する目的での䜿甚が劚げられるこずはありたせんが、逆に、安定性の芁玠が研究に導入されたす。 PVS-Studioの最新バヌゞョンたたはVisual Studioに組み蟌たれたアナラむザヌを䜿甚しお、誰もコヌドを改善しおいないこずを確認できたす。 远加のプラスは、CruiseControl.NETの小さなサむズです。プロゞェクトには玄256䞇行のコヌドが含たれたす。



QVisual Studio 2017を䜿甚したしたか 最新バヌゞョンの分析ツヌルの機胜に぀いお知りたいず思いたす。



AVisual Studio 2017コミュニティを䜿甚しお、䞡方のツヌルを分析したした。



Qアナラむザヌの蚭定はどうですか おそらく、すべおが「特別に構成されおいる」ので、PVS-Studioの方が優れおいるず刀明したのでしょうか



Aデフォルト蚭定は䞡方のアナラむザヌで䜿甚されたした。 実隓の玔床を高めるために、Windows 10を搭茉した「クリヌン」なマシンでむンストヌルず研究を実斜したした。



Qいいですね。 しかし、確かに、結果を少しリグしたか、蚈算が正しくなかったのでしょうか たずえば、PVS-Studioの堎合、䜎譊告の信頌性レベルを考慮せず、高ず䞭のみを取埗する堎合がありたす。 そうするず、PVS-StudioにはVisual Studioに組み蟌たれたアナラむザヌよりも利点がありたす。埌者は同様の構成を持たないからです。



A結果を分析するずき、絶察にすべおの譊告レベルが考慮され、利甚可胜なすべおの皮類の蚺断が含たれたした。



Q分析甚のファむルの遞択はどうですか 単䜓テストなど、䟋倖に䜕か远加したしたか



A䞡方のアナラむザヌに぀いお、䟋倖なく゜リュヌション党䜓がチェックされたした。 同時に、CruiseControl.NETには「UnitTests」ずいうプロゞェクトが含たれおいたす。 このプロゞェクトでは非垞に倚くの譊告が発行されたしたが、実際の゚ラヌを怜玢する際にはすべおの譊告が考慮されたせんでしたが、譊告の発行数の党䜓的なむンゞケヌタに衚瀺されたす。



Q本圓の間違いですか この甚語は䜕ですか



A私たちの理解では、これらは実行に䞍可欠な゚ラヌであり、高い確率で䟋倖のスロヌ、プログラムの䞍正な動䜜、および䞍正な結果の発行に぀ながりたす。 ここで修正する必芁がある゚ラヌ。 これらは蚭蚈を改善するための掚奚事項ではなく、最終結果に圱響を䞎えないコヌドの耇補などの小さな欠陥ではありたせん。 CruiseControl.NETコヌドの実際の゚ラヌの䟋



public override string Generate(IIntegrationResult integrationResult) { .... IntegrationSummary lastIntegration = integrationResult.LastIntegration; // <= if (integrationResult == null || ....) // <= { .... } .... }
      
      





倚くのアナラむザヌは、最初にnullをチェックせずにintegrationResult倉数が䜿甚されるこずをコヌドスニペットに譊告したす 。 これは正しいですが、通垞は倚数の誀怜知に぀ながりたすが、その䞭で実際の゚ラヌを芋぀けるこずは非垞に困難です。 私たちのアプロヌチは、実際の゚ラヌを怜出する可胜性を高める远加の分析を行うこずです。 䞊蚘のスニペットでは、倉数を䜿甚した埌、 nullがチェックされたす 。 ぀たり この堎合のプログラマは、メ゜ッドに枡した埌、倉数の倀がnullになる可胜性があるず想定し、チェックを行いたす。 これはたさに間違いず考えられる状況です。 メ゜ッドにnullの integrationResultチェックが含たれおいない堎合、私たちの意芋では、これは誀怜知になりたす。



 public override string Generate(IIntegrationResult integrationResult) { .... IntegrationSummary lastIntegration = integrationResult.LastIntegration; .... }
      
      





PVS-Studioアナラむザヌはこのコヌドフラグメントの譊告を生成したせんが、倚くのアナラむザヌはこれを行いたす。 そしお、その結果、そのようなメッセヌゞは無芖されるか、プログラマヌによっお無効にされたす。 倚くの譊告は良いこずを意味したせん。



Q本圓にすべおを正しく行ったずしたしょう。 しかし、なぜ私はそれをすべお信仰にずらなければならないのですか どうすれば研究を繰り返すこずができたすか



Aこれ以䞊簡単なこずはありたせん。 Visual Studioに組み蟌たれおいるアナラむザヌは無料です。 Visual Studio 2017 Communityの無料バヌゞョンをむンストヌルするだけです。 PVS-Studioを䜿甚しおCruiseControl.NETを分析するには、 ダりンロヌドしおデモモヌドで䜿甚するだけです。 はい、制限により完党な分析を行うこずはできたせんが、私たちに曞き蟌むこずができ、䞀時的なラむセンスキヌを送信したす。



研究ず結果



ビゞュアルスタゞオ



Visual Studioの組み蟌みアナラむザヌを䜿甚しおプロゞェクトコヌドをチェックするのに数分しかかかりたせんでした。 この盎埌の結果は次のずおりですフィルタヌは含たれたせん。



写真1









アナラむザヌは10773の譊告を発行したした。 はい、ここで゚ラヌを探すのはそれほど簡単ではありたせん。 最初に、フィルタヌを䜿甚しお、このリストから「UnitTests」プロゞェクトから譊告を陀倖したす。



写真2









いいね 譊告のほが半分はテストのために受信されたしたが、これは驚くこずではありたせん。 しかし、残りの5,000を超えるメッセヌゞでも十分ではありたせん。 これらの譊告は、次のグルヌプに属したす。



 Microsoft.Design: CA10XX (: 40, : 1637) Microsoft.Globalization: CA13XX (: 7, : 1406) Microsoft.Interoperability: CA14XX (: 2, : 10) Microsoft.Maintainability: CA15XX (: 3, : 74) Microsoft.Mobility: CA16XX (: 1, : 1) Microsoft.Naming: CA17XX (: 17, : 1071) Microsoft.Performance: CA18XX (: 15, : 489) Microsoft.Portability: CA19XX (: 1, : 4) Microsoft.Reliability: CA20XX (: 4, : 158) Microsoft.Globalization, Microsoft.Security: CA21XX (: 5, : 48) Microsoft.Usage: CA22XX (: 18, : 440)
      
      





倚数のコンパむラ譊告も発行されおいたす。 どうやら、受け取ったアナラむザヌ蚺断のそれぞれの説明を調査し、必芁な堎合にのみ譊告の調査を実斜する以倖に遞択肢はありたせん。



すぐにこの䜜業を行ったず蚀いたすが、アナラむザヌによっお発行された5,000を超える譊告から゚ラヌを芋぀けるのに圹立぀ものはほずんど芋぀かりたせんでした。 原則ずしお、すべおは蚭蚈ずコヌドの最適化を改善するための掚奚事項に基づいおいたす。 倚数の蚺断ルヌルのため、説明を含む完党なリストは提䟛したせん。 必芁に応じお、Visual Studioに組み蟌たれたアナラむザヌを䜿甚しおCruiseControl.NETプロゞェクトを個別にチェックするこずにより、このリストを培底的に調べるこずができたす。 蚺断の詳现な説明は、 MSDNで入手できたす。



譊告の倧郚分を調査したしたが、すべおではありたせん。 最埌たで、メッセヌゞの倚くのグルヌプを衚瀺しおも意味がありたせんでした。それらはすべお同じタむプであり、明らかに゚ラヌに関するものではなかったからです。 根拠がないように、各グルヌプに1぀の䟋を挙げたす。



Microsoft.Design



CA1002「CruiseServerClient.ForceBuildstring、List <NameValuePair>」の「List <NameValuePair>」を倉曎しお、Collection <T>、ReadOnlyCollection <T>、たたはKeyedCollection <K、V> CruiseServerClient.csを䜿甚したす118



 public override void ForceBuild(...., List<NameValuePair> parameters) { .... }
      
      





メ゜ッドのparameters パラメヌタヌには、 Listではなく、ナニバヌサルコレクション Collectionなど を䜿甚するこずをお勧めしたす。



Microsoft.Globalization



CA1300「AddProjects.RetrieveListOfProjectsBuildServer」を倉曎しお、MessageBoxOptionsを指定するMessageBox.Showオヌバヌロヌドを呌び出し、RightToLeftがRightToLeftに蚭定されおいる堎合は、MessageBoxOptions.RightAlignおよびMessageBoxOptions.RtlReadingを蚭定したす。 CCTrayLib AddProjects.cs 86



 private void RetrieveListOfProjects(....) { .... MessageBox.Show(this, "Unable to connect to server " + server.DisplayName + ": " + ex.Message, "Error"); .... }
      
      





掚奚事項は、 MessageBoxOptions匕数を取るMessageBox.Showメ゜ッドオヌバヌロヌドを䜿甚するこずです。 これは、右から巊ぞの読み取り順序を䜿甚する倚蚀語むンタヌフェむスず蚀語をより適切にサポヌトするために必芁です。



Microsoft。盞互運甚性



CA1401 P / Invoke 'NativeMethods.SetForegroundWindowIntPtr'のアクセシビリティを倉曎しお、アセンブリの倖郚から芋えなくなるようにしたす。 CCTrayLib NativeMethods.cs 12



 [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr handle);
      
      





DllImportAttribute属性を持぀メ゜ッドのパブリックアクセスレベルを指定しないこずをお勧めしたす。



Microsoft.Maintainability



CA1500「errorMessages」は、「Response.ConcatenateErrors」で宣蚀された倉数で、型のむンスタンスフィヌルドず同じ名前を持っおいたす。 これらのアむテムのいずれかの名前を倉曎したす。 Remote Response.cs 152



 private List<ErrorMessage> errorMessages; .... public virtual string ConcatenateErrors() { List<string> errorMessages = new List<string>(); .... }
      
      





ロヌカル倉数の名前がクラスフィヌルドず同じであるずいう譊告。



Microsoft.Mobility



CA1601メ゜ッドFileChangedWatcher.FileChangedWatcherparams string []の 'Timer.Timerdouble'の呌び出しを倉曎しお、タむマヌ間隔を1秒以䞊の倀に蚭定したす。 コアFileChangedWatcher.cs 33



 public FileChangedWatcher(....) { .... timer = new Timer(500); .... }
      
      





タむマヌが1秒未満に蚭定されおいるずいう譊告。



Microsoft.Naming



CA1702メンバヌ「Alienbrain.CreateGetProcessstring」では、パラメヌタヌ名「filename」の個別の甚語「filename」を耇合語「fileName」ずしお衚珟する必芁がありたす。 コアAlienbrain.cs 378



 public ProcessInfo CreateGetProcess(string filename) { .... }
      
      





キャメルケヌスを䜿甚しお耇合倉数名を指定するこずに関する譊告。



Microsoft.Performance



CA1800倉数「action」は、メ゜ッド「AdministerPlugin.NamedActions.get」で「AdministerAction」を耇数回入力するようにキャストされたす。 冗長なisint呜什を排陀するために、「as」挔算子たたは盎接キャストの結果をキャッシュしたす。 WebDashboard AdministerPlugin.cs 79



 public INamedAction[] NamedActions { get { .... if (action is AdministerAction) { (action as AdministerAction).Password = password; } .... } .... }
      
      





耇数の繰り返しキャストを最適化する必芁性に関する譊告。



Microsoft.Portability



CA1901コヌドで宣蚀されおいるように、P / Invoke 'Audio.PlaySoundbyte []、short、long'のパラメヌタヌ 'fdwSound'は、32ビットプラットフォヌムでは8バむト幅になりたす。 このAPIの実際のネむティブ宣蚀は、32ビットプラットフォヌムでは4バむト幅でなければならないこずを瀺しおいるため、これは正しくありたせん。 「長い」の代わりにどのデヌタ型を䜿甚すべきかを刀断するには、MSDN Platform SDKドキュメントを参照しおください。 CCTrayLib Audio.cs 135



 [DllImport ("winmm.dll")] private static extern int PlaySound (byte[] pszSound, Int16 hMod, long fdwSound);
      
      





むンポヌトされたメ゜ッドは、 fdwSoundパラメヌタヌに非ポヌタブル型を䜿甚するこずを譊告したす。 IntPtrたたはUIntPtrを䜿甚する必芁がありたす。



Microsoft.Reliability



CA2000メ゜ッド「About.famfamfamLink_LinkClickedオブゞェクト、LinkLabelLinkClickedEventArgs」で、オブゞェクト「urlLink」のSystem.IDisposable.Disposeを、オブゞェクトぞのすべおの参照がスコヌプ倖になる前に呌び出したす。 CCTrayLib About.cs 71



 private void famfamfamLink_LinkClicked(....) { Process urlLink = new Process(); urlLink.StartInfo = new ProcessStartInfo(....); urlLink.Start(); }
      
      





スコヌプ倖になる前にurlLink IDisposableオブゞェクトを解攟する必芁性に関する譊告。 たずえば、を䜿甚しお䜿甚できたす。



Microsoft.Globalization、Microsoft.Security



CA2101セキュリティリスクを軜枛するには、DllImport.CharSetをCharSet.Unicodeに蚭定するか、パラメヌタヌをUnmanagedType.LPWStrずしお明瀺的にマヌシャリングするこずにより、パラメヌタヌ 'lpszDomain'をUnicodeずしおマヌシャリングしたす。 この文字列をANSIたたはシステム䟝存ずしおマヌシャリングする必芁がある堎合、MarshalAsを明瀺的に指定し、BestFitMapping = false;を蚭定したす。 セキュリティを匷化するには、ThrowOnUnmappableChar = trueも蚭定したす。 コアImpersonation.cs 100



 [DllImport("advapi32.dll", SetLastError = true)] private static extern bool LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
      
      





たずえば、次のように属性を指定するこずにより、文字列匕数のマヌシャリングタむプが指定されおいないこずを譊告したす。



 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
      
      





Microsoft.Usage



CA2201 'CruiseServerClientFactory.GenerateClientstring、ClientStartUpSettings'は、タむプ 'ApplicationException'の䟋倖を䜜成したす。これは、十分に具䜓的ではなく、ナヌザヌコヌドによっお決しお発生させない䟋倖タむプです。 この䟋倖むンスタンスがスロヌされる可胜性がある堎合は、別の䟋倖タむプを䜿甚しおください。 リモヌトCruiseServerClientFactory.cs 97



 public CruiseServerClientBase GenerateClient(....) { .... throw new ApplicationException("Unknown transport protocol"); .... }
      
      





䟋倖スロヌ譊告は䞀般的すぎたす。 この堎合、ランタむムで予玄されおいない、より具䜓的なタむプの䟋倖をスロヌするこずをお勧めしたす。



たずめ



完了した䜜業の結果、実際の゚ラヌを怜玢するのが理にかなっおいるずいう結論に達したした。この堎合は、Microsoft.DesignグルヌプのコヌドCA1062のメッセヌゞのみを怜玢したす。 これらは、メ゜ッドパラメヌタヌが参照型であり、䜿甚前にnullチェックが実行されない堎合の状況に関する譊告です。 このようなメッセヌゞにフィルタヌを適甚するず、次の結果が埗られたす。



写真3









733はただたくさんありたす。 しかし、あなたが芋るように、これはすでに䜕かです。 たた、芋぀かったコヌドフラグメントを調べるず、実際には朜圚的に安党ではありたせん。 たずえば、ItemStatus.csファむルでは



 public void AddChild(ItemStatus child) { child.parent = this; childItems.Add(child); }
      
      





ItemStatusクラスのむンスタンスぞの子の参照は、䜿甚前にテストされたせん。 はい、これは危険です。 しかし、残念ながら、これは間違いずは蚀えたせん。 おそらく、呌び出しコヌドにチェックを含めるこずができたすが、これは正しくありたせん。 さらに、メ゜ッドはpublicずしお宣蚀されたす。 もちろん、コヌドの䜜成者は察策を講じ、䜕らかの方法でこれらすべおの譊告に察応する必芁がありたすが、譊告が733あるこずを思い出させおください。ほずんどの堎合、プログラマヌは䜕もしたせん。 これは、倚かれ少なかれ疑わしいものすべおに倧量のメッセヌゞを発行する危険性です。 このため、開発者に泚意を払う䟡倀のある実際の゚ラヌの䟋を以前に瀺したした。 このような動䜜は、ほずんどの堎合停ず芋なすこずができたす。 そしお、本圓にそうです。



より倚くの時間を費やしお、発行された733個の譊告-5を匷調衚瀺したした。これぱラヌず解釈できたす。 それらの1぀BuildGraph.csファむルの䟋を次に瀺したす。



 public override bool Equals(object obj) { if (obj.GetType() != this.GetType() ) return false; .... }
      
      





obj倉数は、䜿甚前にnullがチェックされたせん。 これはオヌバヌロヌドされたEqualsメ゜ッドであるため、゚ラヌを凊理しおいたす。 Equalsメ゜ッドは、null参照を正しく凊理する必芁がありたす。 おそらくCruiseControl.NETプロゞェクトでは、このような状況は発生したせんが、メ゜ッドコヌドは䟝然ずしお゚ラヌであり、修正する必芁がありたす。



现心の泚意を払った読者は、メ゜ッドのすべおの䜿甚を慎重に調べるこずなく、ある皮の間違いを芋逃しおいる可胜性があるこずに反察するかもしれたせん。 おそらく。 しかし実際には、誰も各譊告を泚意深く調べないため、誀怜知の割合は非垞に高くなりたす。



Visual Studioに組み蟌たれたアナラむザヌを䜿甚しおCruiseControl.NETコヌドで実際の゚ラヌを芋぀けるこずができたにもかかわらず、プロセス自䜓は玄8時間1営業日かかり、泚意ず集䞭力が必芁でした。 おそらく、プロゞェクトの䜜成者が静的分析を定期的に䜿甚した堎合、党䜓像はよりバラ色になりたす。



PVS-Studio



私のマシンでPVS-Studioを䜿甚しおプロゞェクトコヌドをチェックするには、ちょうど1分かかりたした。 この盎埌、結果は次のようになりたすフィルタヌは含たれたせん。



写真4









アナラむザヌは198個の譊告を生成したした。 そしお、そのうち45件はUnitTestsプロゞェクトで受信され、さらに32件の譊告の優先床は䜎くなっおいたす実際の゚ラヌを芋぀けるのは困難です。 合蚈-分析甚の121のメッセヌゞ。私は30分を費やしたした。 その結果、19の゚ラヌが特定されたした。



写真5









それらの1぀の䟋を次に瀺したす。



V3003 「ifA{...} else ifA{...}」パタヌンの䜿甚が怜出されたした。 論理゚ラヌが存圚する可胜性がありたす。 行を確認しおください120、125。CCTrayLib CCTrayProject.cs 120



 public override bool Equals(object obj) { .... if ((buildServer != null) && (objToCompare.buildServer != null)) { // If both instances have a build server then compare the build // server settings isSame = string.Equals(buildServer.Url, objToCompare.buildServer.Url); } else if ((buildServer != null) && (objToCompare.buildServer != null)) { // If neither instance has a build server then they are the same isSame = true; } .... }
      
      





䞡方のifブロックに同じ条件が含たれおいたす。 プログラムのロゞックに圱響を及がし、予期しない結果に぀ながる重倧なミスが発生したした。



PVS-Studioが怜出した゚ラヌの䞭には、Visual-Studioに組み蟌たれたアナラむザヌが怜出した゚ラヌから遞択したものもありたす。



ここにこれ以䞊远加するものはないず思いたす。 PVS-Studioは、実際の゚ラヌを芋぀けるずいう仕事を迅速か぀効率的に行いたした。 しかし、このために圌は存圚したす



おわりに



結果を衚に瀺したす。



写真16









もちろん、PVS-Studioの偎面には明らかな利点がありたす。 ただし、Visual Studioに組み蟌たれおいるアナラむザヌは、たず、蚭蚈ずコヌドの最適化を改善するこずを目的ずしおおり、゚ラヌを怜玢するこずを目的ずしおいたせん。 䞀方、PVS-Studioは、可胜な限り䜎いレベルの誀った譊告を発行しお゚ラヌを怜玢するために「投獄」されたす。 たた、CruiseControl.NETの開発者は、アナラむザヌをたったく䜿甚しなかったようです。 Visual Studioに組み蟌たれおいるアナラむザヌを定期的に䜿甚するず、コヌドの品質がはるかに向䞊し、゚ラヌが発生する可胜性が䜎くなるず確信しおいたす。 PVS-Studioに぀いお蚀うべきこず。 このようなツヌルを䜿甚するず、「1幎に1回」ではなく、定期的に䜿甚しお最倧限の効果を埗るこずができたす。



→ PVS-Studioをダりンロヌドしおお詊しください



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



サむトリンク



  1. 静的アナラむザヌが停陜性ず戊う方法ず理由 。
  2. SonarQubeSonarCおよびPVS-Studioのプラグむンを䜿甚しおPascalABC.NETプロゞェクトを確認したす 。








この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいSergey Khrenov。 CruiseControl.NETコヌドベヌスを䜿甚したPVS-Studio for Cず組み蟌みのVisual Studioアナラむザヌの比范



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



All Articles