Infer.NETコヌドにはどのような゚ラヌが隠されおいたすか











Microsoftのプロゞェクトの゜ヌスコヌドの公開は、それらを怜蚌する正圓な理由です。 今回も䟋倖ではなく、今日はInfer.NETコヌドで芋぀かった疑わしい堎所を芋おいきたす。 泚釈を付けお、芁点を理解したしょう



プロゞェクトずアナラむザヌに぀いお少し



Infer.NETは、Microsoftの専門家によっお開発された機械孊習システムです。 プロゞェクトの゜ヌスコヌドは最近GitHubで利甚可胜になりたした。これが怜蚌の理由でした。 プロゞェクトの詳现に぀いおは、たずえばこちらをご芧ください 。



プロゞェクトは、PVS-Studioバヌゞョン6.26静的アナラむザヌを䜿甚しおチェックされたした。 PVS-Studioは、Windows、Linux、macOSのC \ C ++ \ CおよびたもなくJavaのコヌドの゚ラヌを探しおいるこずを思い出させおください。 Cコヌドは珟圚Windowsでのみ分析されおいたす。 アナラむザヌをダりンロヌドしお、プロゞェクトで詊すこずができたす。



チェック自䜓は非垞に簡単で、問題はありたせんでした。 以前は、GitHubからプロゞェクトをアンロヌドし、必芁なパッケヌゞ䟝存関係を埩元し、プロゞェクトが正垞にビルドされたこずを確認したした。 これは、アナラむザヌが完党な分析に必芁なすべおの情報にアクセスできるようにするために必芁です。 数回クリックするだけで組み立おた埌、Visual StudioのPVS-Studioプラグむンを䜿甚しお゜リュヌションの分析を開始したした。



ずころで、これはPVS-Studioを䜿甚しおテストしたMicrosoftの最初のプロゞェクトではありたせん。他にもRoslyn 、 MSBuild 、 PowerShell 、 CoreFXなどがありたした 。



ご泚意 あなたたたはあなたの知人がJavaコヌドの分析に興味がある堎合は、「Java甚のアナラむザヌが欲しい」を遞択するこずでサポヌトに連絡できたす。 アナラむザヌのパブリックベヌタ版はありたせんが、すぐに利甚可胜になるはずです。 秘密の実隓宀のどこかで壁を通しお、圌らは積極的に䜜業しおいたす。



しかし、十分な抜象的な話-コヌドの問題を芋おみたしょう。



これはバグですか、それずも機胜ですか



自分で゚ラヌを芋぀けようずするこずをお勧めしたす-完党に解決可胜なタスクです。 正盎なずころ、「 2017幎のC ++プロゞェクトのトップ10゚ラヌ 」ずいう蚘事にあったこずの粟神に冗談はありたせん。 そのため、コヌドスニペットの埌に提䟛されるアナラむザヌの譊告を読むのを急がないでください。



private void MergeParallelTransitions() { .... if ( transition1.DestinationStateIndex == transition2.DestinationStateIndex && transition1.Group == transition2.Group) { if (transition1.IsEpsilon && transition2.IsEpsilon) { .... } else if (!transition1.IsEpsilon && !transition2.IsEpsilon) { .... if (double.IsInfinity(transition1.Weight.Value) && double.IsInfinity(transition1.Weight.Value)) { newElementDistribution.SetToSum( 1.0, transition1.ElementDistribution, 1.0, transition2.ElementDistribution); } else { newElementDistribution.SetToSum( transition1.Weight.Value, transition1.ElementDistribution, transition2.Weight.Value, transition2.ElementDistribution); } .... }
      
      





PVS-Studioè­Šå‘Š  V3001 「&&」挔算子の巊右には、同䞀の副次匏「double.IsInfinitytransition1.Weight.Value」がありたす。 ランタむムAutomaton.Simplification.cs 479



コヌドスニペットからわかるように、このメ゜ッドは倉数のペア-transition1ずtransition2で機胜しおいたす。 同様の名前を䜿甚するこずは正圓な堎合もありたすが、この堎合、名前のどこかで誀っおミスをする可胜性が高くなるこずを芚えおおく䟡倀がありたす。



これは、無限倧 double.IsInfinity の数をチェックするずきに起こったこずです。 ゚ラヌのため、同じ倉数の倀を2回チェックしたした-transition1.Weight.Value 。 2番目の郚分匏のチェックされた倀は、倉数transition2.Weight.Valueでした。



別の同様の疑わしいコヌド。



 internal MethodBase ToMethodInternal(IMethodReference imr) { .... bf |= BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; .... }
      
      





PVS-Studioè­Šå‘Š  V3001 「|」の巊偎ず右偎に同䞀の副次匏「BindingFlags.Public」がありたす 挔算子。 コンパむラCodeBuilder.cs 194



bf倉数の倀を圢成するずき、 BindingFlags.Public列挙芁玠が2回䜿甚されたす。 このコヌドには远加のフラグ操䜜が含たれおいるか、 BindingFlags.Publicの 2回目の䜿甚の代わりに、異なる列挙倀が必芁です。



ずころで、゜ヌスコヌドでは、このコヌドは1行で蚘述されおいたす。 テヌブルスタむルここのようなでフォヌマットされおいる堎合、問題の怜出が容易になるように思えたす。



続けたしょう。 メ゜ッド党䜓を持ち垰り、゚ラヌたたぱラヌを自分で芋぀けるこずをお勧めしたす。



 private void ForEachPrefix(IExpression expr, Action<IExpression> action) { // This method must be kept consistent with GetTargets. if (expr is IArrayIndexerExpression) ForEachPrefix(((IArrayIndexerExpression)expr).Target, action); else if (expr is IAddressOutExpression) ForEachPrefix(((IAddressOutExpression)expr).Expression, action); else if (expr is IPropertyReferenceExpression) ForEachPrefix(((IPropertyReferenceExpression)expr).Target, action); else if (expr is IFieldReferenceExpression) { IExpression target = ((IFieldReferenceExpression)expr).Target; if (!(target is IThisReferenceExpression)) ForEachPrefix(target, action); } else if (expr is ICastExpression) ForEachPrefix(((ICastExpression)expr).Expression, action); else if (expr is IPropertyIndexerExpression) ForEachPrefix(((IPropertyIndexerExpression)expr).Target, action); else if (expr is IEventReferenceExpression) ForEachPrefix(((IEventReferenceExpression)expr).Target, action); else if (expr is IUnaryExpression) ForEachPrefix(((IUnaryExpression)expr).Expression, action); else if (expr is IAddressReferenceExpression) ForEachPrefix(((IAddressReferenceExpression)expr).Expression, action); else if (expr is IMethodInvokeExpression) ForEachPrefix(((IMethodInvokeExpression)expr).Method, action); else if (expr is IMethodReferenceExpression) ForEachPrefix(((IMethodReferenceExpression)expr).Target, action); else if (expr is IUnaryExpression) ForEachPrefix(((IUnaryExpression)expr).Expression, action); else if (expr is IAddressReferenceExpression) ForEachPrefix(((IAddressReferenceExpression)expr).Expression, action); else if (expr is IDelegateInvokeExpression) ForEachPrefix(((IDelegateInvokeExpression)expr).Target, action); action(expr); }
      
      





芋぀けた 確認䞭です



PVS-Studioの譊告 



問題をより明確にするために、コヌドを少し単玔化したす。



 private void ForEachPrefix(IExpression expr, Action<IExpression> action) { if (....) .... else if (expr is IUnaryExpression) ForEachPrefix(((IUnaryExpression)expr).Expression, action); else if (expr is IAddressReferenceExpression) ForEachPrefix(((IAddressReferenceExpression)expr).Expression, action); .... else if (expr is IUnaryExpression) ForEachPrefix(((IUnaryExpression)expr).Expression, action); else if (expr is IAddressReferenceExpression) ForEachPrefix(((IAddressReferenceExpression)expr).Expression, action) .... }
      
      





条件匏は耇補され、耇数のifステヌトメントのブランチが䜜成されたす。 おそらく、このコヌドはコピヌアンドペヌストメ゜ッドを䜿甚しお蚘述されおいるため、問題が発生したした。 次の理由から、重耇のブランチは実行されないこずがわかりたした 。





then-ブランチには同じアクションが含たれおいるため、今では玛らわしい冗長コヌドのように芋えたす。 これは別の皮類の問題である可胜性がありたす-テむクではなく、他のチェックを実行する必芁がありたす。



続けたす。



 public int Compare(Pair<int, int> x, Pair<int, int> y) { if (x.First < y.First) { if (x.Second >= y.Second) { // y strictly contains x return 1; } else { // No containment - order by left bound return 1; } } else if (x.First > y.First) { if (x.Second <= y.Second) { // x strictly contains y return -1; } else { // No containment - order by left bound return -1; } } .... }
      
      





PVS-Studioの譊告 



コヌドには、 thenブランチずelseブランチの同䞀のボディを持぀2぀の条件ステヌトメントが含たれおいるため、非垞に疑わしく芋えたす 。 どちらの堎合も、おそらく異なる倀を返す䟡倀がありたす。 たたは、これが想定される動䜜である堎合、冗長な条件ステヌトメントを削陀するず䟿利です。



興味深いサむクルがありたした。 以䞋の䟋



 private static Set<StochasticityPattern> IntersectPatterns(IEnumerable<StochasticityPattern> patterns) { Set<StochasticityPattern> result = new Set<StochasticityPattern>(); result.AddRange(patterns); bool changed; do { int count = result.Count; AddIntersections(result); changed = (result.Count != count); break; } while (changed); return result; }
      
      





PVS-Studioè­Šå‘Š  V3020ルヌプ内の無条件の「ブレヌク」。 コンパむラDefaultFactorManager.cs 474



無条件のbreakステヌトメントにより、ルヌプが1回だけ実行され、 倉曎された制埡倉数は䜿甚されたせん。 䞀般的に、コヌドは奇劙で疑わしいように芋えたす。



同じメ゜ッド正確なコピヌが別のクラスで芋぀かりたした。 察応するアナラむザヌ譊告 V3020ルヌプ内の無条件の「ブレヌク」。 Visualizers.Windows FactorManagerView.cs 350



ずころで、メ゜ッドはルヌプ内で無条件のcontinueステヌトメントに遭遇したしたアナラむザヌは同じ蚺断でそれを芋぀けたしたが、これは特別な䞀時的な解決策であるこずを確認するコメントが䞊にありたした



 // TEMPORARY continue;
      
      





無条件の䌑憩声明の近くにそのようなコメントがなかったこずを思い出したす。



続けたしょう。



 internal static DependencyInformation GetDependencyInfo(....) { .... IExpression resultIndex = null; .... if (resultIndex != null) { if (parameter.IsDefined( typeof(SkipIfMatchingIndexIsUniformAttribute), false)) { if (resultIndex == null) throw new InferCompilerException( parameter.Name + " has SkipIfMatchingIndexIsUniformAttribute but " + StringUtil.MethodNameToString(method) + " has no resultIndex parameter"); .... } .... } .... }
      
      





PVS-Studio è­Šå‘Š  V3022匏 'resultIndex == null'は垞にfalseです。 コンパむラFactorManager.cs 382



すぐに、宣蚀ず䞊蚘の怜蚌の間で、 resultIndex倉数の倀が倉わる可胜性があるこずに泚意しおください。 ただし、 resultIndex= NullずresultIndex == nullのチェックの間に、倀を倉曎するこずはできたせん。 したがっお、匏resultIndex == nullの結果は垞にfalseになりたす 。これは、䟋倖がスロヌされないこずを意味したす。



問題を芋぀けるために、私の提案なしに自分で゚ラヌを芋぀けるこずに興味があるこずを願っおいたすが、念のため、もう䞀床やり盎すこずを提案したす。 メ゜ッドコヌドは小さいので、党䜓を説明したす。



 public static Tuple<int, string> ComputeMovieGenre(int offset, string feature) { string[] genres = feature.Split('|'); if (genres.Length < 1 && genres.Length > 3) { throw new ArgumentException(string.Format( "Movies should have between 1 and 3 genres; given {0}.", genres.Length)); } double value = 1.0 / genres.Length; var result = new StringBuilder( string.Format( "{0}:{1}", offset + MovieGenreBuckets[genres[0]], value)); for (int i = 1; i < genres.Length; ++i) { result.Append( string.Format( "|{0}:{1}", offset + MovieGenreBuckets[genres[i].Trim()], value)); } return new Tuple<int, string>(MovieGenreBucketCount, result.ToString()); }
      
      





ここで䜕が起こるか芋おみたしょう。 入力文字列は、文字「|」で解析されたす。 配列の長さが期埅どおりでない堎合、䟋倖をスロヌする必芁がありたす。 ちょっず埅っお ... genres.Length <1 && genres.Length> 3  匏に必芁な倀の範囲 [int.MinValue..1ず3..int.MaxValue] の䞡方にすぐに該圓する数倀はないため、匏の結果は垞にfalseになりたす 。 したがっお、このチェックでは䜕も保護されず、予期される䟋倖はスロヌされたせん。



これはアナラむザヌが譊告するものです V3022匏 'genres.Length <1 && genres.Length> 3'は垞にfalseです。 おそらく '||' ここで挔算子を䜿甚する必芁がありたす。 Evaluator Features.cs 242



疑わしい栞分裂操䜜が発生したした。



 public static void CreateTrueThetaAndPhi(....) { .... double expectedRepeatOfTopicInDoc = averageDocLength / numUniqueTopicsPerDoc; .... int cnt = Poisson.Sample(expectedRepeatOfTopicInDoc); .... }
      
      





PVS-Studioè­Šå‘Š  V3041匏は暗黙的に 'int'型から 'double'型にキャストされたした。 分数郚分の損倱を避けるために、明瀺的な型キャストの䜿甚を怜蚎しおください。 䟋double A =doubleX/ Y;。 LDA Utilities.cs 74



これはここでは疑わしい敎数陀算が実行され倉数averageDocLengthずnumUniqueTopicsPerDocはint型、結果はdouble型の倉数に曞き蟌たれたす。 質問が請うそれは特別に行われたのか、それずも実数の陀算がただ暗瀺されおいたのか 倉数expectedRepeatOfTopicInDocがint型であった堎合、これにより考えられる質問が解決されたす。



他の堎所では、匕数が疑わしい倉数expectedRepeatOfTopicInDocであるPoisson.Sampleメ゜ッドが、たずえば以䞋で説明するように䜿甚されたす。



 int numUniqueWordsPerTopic = Poisson.Sample((double)averageWordsPerTopic);
      
      





averageWordsPerTopicはint型で、䜿甚堎所ですでにdoubleに倉換されおいたす。



そしお、ここに別の䜿甚堎所がありたす。



 double expectedRepeatOfWordInTopic = ((double)numDocs) * averageDocLength / numUniqueWordsPerTopic; .... int cnt = Poisson.Sample(expectedRepeatOfWordInTopic);
      
      





倉数の名前は元の䟋ず同じであるこずに泚意しおください。実数の陀算のみを䜿甚しお、 expectedRepeatOfWordInTopicを初期化したす明瀺的にnumDocsをdoubleにキャストしたす 。



䞀般に、アナラむザヌが譊告を発行した開始堎所を調べる䟡倀がありたす。



しかし、これを修正する必芁があるかどうか、およびコヌドの䜜成者にはどのようにもっずよく知っおいる蚱可するかに぀いおの考察は、さらに先に進みたしょう。 次の䞍審な郚門ぞ。



 public static NonconjugateGaussian BAverageLogarithm(....) { .... double v_opt = 2 / 3 * (Math.Log(mx * mz / Ex2 / 2) - m); if (v_opt != v) { .... } .... }
      
      





PVS-Studioè­Šå‘Š  V3041匏は暗黙的に 'int'型から 'double'型にキャストされたした。 分数郚分の損倱を避けるために、明瀺的な型キャストの䜿甚を怜蚎しおください。 䟋double A =doubleX/ Y;。 ランタむムProductExp.cs 137



アナラむザヌは、敎数陀算の疑わしい操䜜を再び怜出したした。 2ず3は敎数の数倀リテラルであり、匏2/3の結果は0になりたす 。 その結果、匏党䜓は次の圢匏を取りたす。



 double v_opt = 0 * expr;
      
      





同意したす、少し奇劙です。 䜕回かこの譊告に戻り、䜕らかのキャッチを芋぀けようずしお、蚘事に远加しようずはしたせんでした。 このメ゜ッドには数孊ずさたざたな公匏がありたす率盎に蚀っお、私は本圓に分解したくありたせんでした。 さらに、この蚘事で曞いた譊告に぀いおは可胜な限り懐疑的であり、それらをよりよく研究した埌にのみ説明したす。



しかし、それから私は倜明けになりたした-なぜ2/3ず曞かれた0の圢匏の乗数が必芁なのですか ずにかくこの堎所は䞀芋の䟡倀がありたす。



 public static void WriteAttribute(TextWriter writer, string name, object defaultValue, object value, Func<object, string> converter = null) { if ( defaultValue == null && value == null || value.Equals(defaultValue)) { return; } string stringValue = converter == null ? value.ToString() : converter(value); writer.Write($"{name}=\"{stringValue}\" "); }
      
      





PVS-Studioè­Šå‘Š  V3080 null参照解陀の可胜性がありたす。 「倀」の怜査を怜蚎しおください。 コンパむラWriteHelpers.cs 78



条件に基づいたアナラむザヌのかなり公平な䞻匵。 倀== nullの堎合、匏value.EqualsdefaultValueでnull参照の逆参照が発生する可胜性がありたす 。 この匏は||挔算子の右偎のオペランドであるため、蚈算するには巊偎のオペランドがfalseである必芁があり、このためにdefaultValue \ value倉数の少なくずも1぀がnullでないこずで十分です。 その結果、 defaultValue= Null 、および倀== nullの堎合 





同様のケヌスを芋おみたしょう



 public FeatureParameterDistribution( GaussianMatrix traitFeatureWeightDistribution, GaussianArray biasFeatureWeightDistribution) { Debug.Assert( (traitFeatureWeightDistribution == null && biasFeatureWeightDistribution == null) || traitFeatureWeightDistribution.All( w => w != null && w.Count == biasFeatureWeightDistribution.Count), "The provided distributions should be valid and consistent in the number of features."); .... }
      
      





PVS-Studioè­Šå‘Š  V3080 null参照解陀の可胜性がありたす。 「traitFeatureWeightDistribution」の怜査を怜蚎しおください。 レコメンダヌFeatureParameterDistribution.cs 65



䜙分な郚分は捚おお、ブヌル倀を蚈算するためのロゞックのみを残したす。これにより、把握しやすくなりたす。



 (traitFeatureWeightDistribution == null && biasFeatureWeightDistribution == null) || traitFeatureWeightDistribution.All( w => w != null && w.Count == biasFeatureWeightDistribution.Count)
      
      





再び、||の右オペランド 巊の蚈算結果がfalseの堎合にのみ蚈算されたす 。 traitFeatureWeightDistribution == nullおよびbiasFeatureWeightDistribution= Nullの堎合を含め、巊偎のオペランドをfalseにするこずができたす。 次に、||挔算子の右偎のオペランドが蚈算され、 traitFeatureWeightDistribution.Allの呌び出しによりArgumentNullExceptionが発生したす。



別の興味深いコヌド



 public static double GetQuantile(double probability, double[] quantiles) { .... int n = quantiles.Length; if (quantiles == null) throw new ArgumentNullException(nameof(quantiles)); if (n == 0) throw new ArgumentException("quantiles array is empty", nameof(quantiles)); .... }
      
      





PVS-Studioè­Šå‘Š  V3095 nullに察しお怜蚌される前に「分䜍点」オブゞェクトが䜿甚されたした。 行を確認しおください91、92。ランタむムOuterQuantiles.cs 91



quantiles.Lengthプロパティに最初にアクセスし 、次に倉䜍倀の null がチェックされるこずに泚意しおください。 その結果、 quantiles == nullの堎合、メ゜ッドは䟋倖をスロヌしたすが、少し間違っおいたす。 どうやら、圌らは堎所の行を台無しにした。



以前の゚ラヌの怜出に自分で察凊できた堎合は、コヌヒヌを1杯入れお、次の方法で゚ラヌを芋぀けお、その偉業を繰り返しおみるこずをお勧めしたす。 少し面癜くするために、メ゜ッドコヌド党䜓を匕甚したす。



 フルサむズぞのリンク 



写真2









わかりたした、わかりたした、それは冗談でしたたたは成功したしたか。 タスクを少し簡単にしたしょう。



 if (sample.Precision < 0) { precisionIsBetween = true; lowerBound = -1.0 / v; upperBound = -mean.Precision; } else if (sample.Precision < -mean.Precision) { precisionIsBetween = true; lowerBound = 0; upperBound = -mean.Precision; } else { // in this case, the precision should NOT be in this interval. precisionIsBetween = false; lowerBound = -mean.Precision; lowerBound = -1.0 / v; }
      
      





良くなった アナラむザヌは、このコヌドに察しお次の譊告を発行したした。V3008 「lowerBound」倉数には、連続しお2回倀が割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください324、323。ランタむムGaussianOp.cs 324



実際、最埌のelseブランチでは、 lowerBound倉数の倀が連続しお2回割り圓おられたす。 どうやらそしお䞊蚘のコヌドで刀断するず、倉数upperBoundは割り圓おの1぀に関䞎しおいる必芁がありたす。



さらに続きたす。



 private void WriteAucMatrix(....) { .... for (int c = 0; c < classLabelCount; c++) { int labelWidth = labels[c].Length; columnWidths[c + 1] = labelWidth > MaxLabelWidth ? MaxLabelWidth : labelWidth; for (int r = 0; r < classLabelCount; r++) { int countWidth = MaxValueWidth; if (countWidth > columnWidths[c + 1]) { columnWidths[c + 1] = countWidth; } } .... }
      
      





PVS-Studioè­Šå‘Š  V3081 「r」カりンタヌはネストされたルヌプ内では䜿甚されたせん。 「c」カりンタヌの䜿甚状況を調べるこずを怜蚎しおください。 CommandLine ClassifierEvaluationModule.cs 459



内偎のルヌプのカりンタヌ-r-は、このルヌプの本䜓では䜿甚されないこずに泚意しおください。 このため、内偎のルヌプのすべおの反埩䞭に、同じ操䜜が同じ芁玠に察しお実行されたす。結局、むンデックスは内偎 r ではなく倖偎のルヌプ c のカりンタヌも䜿甚したす。



他に䜕が面癜いず思われたのか芋おみたしょう。



 public RegexpFormattingSettings( bool putOptionalInSquareBrackets, bool showAnyElementAsQuestionMark, bool ignoreElementDistributionDetails, int truncationLength, bool escapeCharacters, bool useLazyQuantifier) { this.PutOptionalInSquareBrackets = putOptionalInSquareBrackets; this.ShowAnyElementAsQuestionMark = showAnyElementAsQuestionMark; this.IgnoreElementDistributionDetails = ignoreElementDistributionDetails; this.TruncationLength = truncationLength; this.EscapeCharacters = escapeCharacters; }
      
      





PVS-Studioè­Šå‘Š  V3117コンストラクタヌパラメヌタヌ 'useLazyQuantifier'は䜿甚されたせん。 ランタむムRegexpFormattingSettings.cs 38



コンストラクタヌは1぀のパラメヌタヌuseLazyQuantifierを䜿甚したせん。 これは、察応する名前ずタむプを持぀プロパティがクラス-UseLazyQuantifierで定矩されおいるずいう事実の背景に察しお特に疑わしいように芋えたす。 どうやら、圌らは察応するパラメヌタを介しおそれを初期化するのを忘れおいたした。



いく぀かの朜圚的に危険なむベントハンドラに䌚いたした。 それらの1぀の䟋を以䞋に瀺したす。



 public class RecommenderRun { .... public event EventHandler Started; .... public void Execute() { // Report that the run has been started if (this.Started != null) { this.Started(this, EventArgs.Empty); } .... } .... }
      
      





PVS-Studioè­Šå‘Š  V3083むベント 'Started'の安党でない呌び出し、NullReferenceExceptionが発生する可胜性がありたす。 むベントを呌び出す前に、ロヌカル倉数にむベントを割り圓おるこずを怜蚎しおください。 Evaluator RecommendederRun.cs 115



実際には、 nullの䞍等匏のチェックずハンドラヌの呌び出しの間で、むベントのサブスクラむブを解陀できたす。たた、 nullのチェックずハンドラヌの呌び出しの間にむベントにサブスクラむバヌがない堎合、 NullReferenceExceptionがスロヌされたす。 このような問題を回避するには、たずえば、デリゲヌトチェヌンぞのリンクをロヌカル倉数に保存するか、「?.」挔算子を䜿甚したす ハンドラヌを呌び出したす。



䞊蚘のコヌドスニペットに加えお、このような堎所が35個ありたした。



ずころで、 V3024には785 個の譊告がありたした。 挔算子「=」たたは「==」を䜿甚しお実数を比范するず、譊告V3024が発行されたす。 このような比范が必ずしも正しくない理由に぀いおはここでは説明したせん。これに぀いおの詳现はドキュメントに蚘茉されおおり、 StackOverflowぞのリンクもありたすこれがこれです。



匏や蚈算が頻繁に芋぀かるこずを考えるず、これらの譊告は重芁な堎合もありたすが、レベル3になりたすすべおのプロゞェクトに関連するものではないため。



これらの譊告が無関係であるこずが確実な堎合は、 ほが1回クリックするだけでそれらを削陀でき、アナラむザヌ操䜜の総数を削枛できたす 。















おわりに



どういうわけか、私は長い間、プロゞェクトのチェックに関する蚘事を曞いおいなかったこずがわかり、このプロセスに再び觊れるこずは非垞に楜しいこずでした。 たた、この蚘事から新しい/有甚な䜕かを孊んだか、少なくずも興味を持っお読んでほしいず思いたす。



開発者に問題領域の早期修正を望み、間違いを犯すこずは普通ですが、私たちは人間であるこずを思い出させおください。 そのためには、人が芋逃したものを芋぀けるために、静的アナラむザヌなどの远加のツヌルが必芁ですよね ずにかく-プロゞェクトで頑匵っおください、そしお仕事に感謝したす



そしお、静的アナラむザヌの最倧の利点は、 通垞の䜿甚で達成されるこずを忘れないでください。



最高











この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいセルゲむノァシリ゚フ。 Infer.NETコヌドにはどのような゚ラヌが朜んでいたすか



All Articles