ソースC#Unityコードの確認

写真5

最近、多くの人々のために待望のイベントが起こりました-Unity Technologiesは、Unityゲームエンジン用のオリジナルのC#コードをGitHubに無料でダウンロードするために投稿しました。 エンジンとエディターのコードが表示されます。 もちろん、特にC#でプロジェクトをチェックすることについて多くの記事を書いていないので、特に通り抜けることはできませんでした。 Unityは、提供されたソースの使用を参照目的のみに許可しています。 それがまさに私たちがやることです。 UnityコードでPVS-Studio 6.23の最新バージョンをテストします。

はじめに


以前にUnity Validation に関する記事を書きまし 。 当時、分析に使用できるC#コードはそれほど多くありませんでした:一部のコンポーネント、ライブラリ、および使用例。 それにもかかわらず、この記事の著者はいくつかの興味深いエラーを見つけることができました。

今回Unityは何を喜ばれましたか? 「喜んで」と言いますが、プロジェクトの作者を怒らせないことを願っています。 さらに、 GitHubに表示される元のUnity C#コードのボリュームは、拡張子「cs」の2058ファイルで約40万行(空の行を除く)です。 これは非常に多く、アナライザーは非常に幅広い分野の活動を行っていました。

次に結果について。 分析を開始する前に、見つかったエラーのCWE分類に従ってコードの表示モードをオンにし、信頼性の3番目のレベル(低)の警告を抑制するモードをアクティブにして、作業を少し簡略化しました。 これらの設定は、Visual Studio開発環境のPVS-Studioドロップダウンメニューと、アナライザー設定で使用できます。 この方法で信頼性の低い警告を取り除いた後、Unityソースコードを分析しました。その結果、最初の信頼性レベル(High)の警告181と2番目の信頼性レベル(Medium)の警告181を受け取りました。

多くの警告があるので、受け取ったすべての警告を絶対に勉強しませんでした。 開発者や愛好家は、Unityテストを自分で行うことにより、簡単に詳細な分析を行うことができます。 このために、PVS-Studioは試用モードと無料使用モードを提供します。 また、企業は製品購入して、ライセンスに加えて、迅速かつ詳細なサポートを受けることができます

ほぼすべての警告グループで、1回または2回の試行ですぐに本当のエラーを見つけることができたという事実から判断すると、Unityには多くのエラーがあります。 そして、はい、彼らは多様です。 最も興味深い間違いを探りましょう。

検証結果


フラグに問題がある

PVS-Studio警告: V3001 「|」の左と右に同一のサブ式「MethodAttributes.Public」があります 演算子。 SyncListStructProcessor.cs 240
MethodReference GenerateSerialization() { .... MethodDefinition serializeFunc = new MethodDefinition("SerializeItem", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Public | // <= MethodAttributes.HideBySig, Weaver.voidType); .... } 

MethodAttributes列挙のフラグを組み合わせるときにエラー発生しました: Public値が2回使用されました。 おそらく、これはコードのフォーマットが不十分なためです。

GenerateDeserializationメソッドのコードでも同様のエラーが発生しました
コピーペースト

PVS-Studio警告: V3001 「||」の左と右に同一のサブ式「format == RenderTextureFormat.ARGBFloat」があります 演算子。 RenderTextureEditor.cs 87
 public static bool IsHDRFormat(RenderTextureFormat format) { Return (format == RenderTextureFormat.ARGBHalf || format == RenderTextureFormat.RGB111110Float || format == RenderTextureFormat.RGFloat || format == RenderTextureFormat.ARGBFloat || format == RenderTextureFormat.ARGBFloat || format == RenderTextureFormat.RFloat || format == RenderTextureFormat.RGHalf || format == RenderTextureFormat.RHalf); } 

以前にフォーマットされたコードのスニペットを与えたので、エラーは視覚的に簡単に検出されます: RenderTextureFormat.ARGBFloatで2回比較されます 元のコードでは、これは少し異なります。

写真3


おそらく、2つの同一の比較の1 つではRenderTextureFormat列挙の他の値を使用する必要があります。

ダブルジョブ

PVS-Studio警告: V3008 CWE-563 'fail'変数には、連続して2回値が割り当てられます。 おそらくこれは間違いです。 チェックライン:1633、1632。UNetWeaver.cs 1633
 class Weaver { .... public static bool fail; .... static public bool IsValidTypeToGenerate(....) { .... if (....) { .... Weaver.fail = true; fail = true; return false; } return true; } .... } 

Weaver.failfailWeaverクラスの同じ静的フィールドであるため、変数はtrueに 2回設定されます 。 おそらくここには重大なエラーはありませんが、コードには間違いなく注意が必要です。

オプションなし

PVS-Studio警告: V3009 CWE-393このメソッドが常に1つの同じ値「false」を返すのは奇妙です。 ProjectBrowser.cs 1417
 // Returns true if we should early out of OnGUI bool HandleCommandEventsForTreeView() { .... if (....) { .... if (....) return false; .... } return false; } 

メソッドは常にfalseを返します 。 最初のコメントに注意してください。

結果を忘れました

PVS-Studio警告: V3010 CWE-252関数 'Concat'の戻り値を使用する必要があります。 AnimationRecording.cs 455
 static public UndoPropertyModification[] Process(....) { .... discardedModifications.Concat(discardedRotationModifications); return discardedModifications.ToArray(); } 

2つの配列を連結するとき、 discardedModificationsおよびdiscardRotationModificationsは結果を保存するのを忘れていました。 おそらくプログラマーは、結果がdiscardedModifications配列にすぐに反映されることを提案しました。 しかし、これはそうではありません。 その結果、 discardedModifications配列の元のバージョンがメソッドから返されます。 コードは次のように修正する必要があります。
 static public UndoPropertyModification[] Process(....) { .... return discardedModifications.Concat(discardedRotationModifications) .ToArray(); } 

チェックなし

PVS-Studio警告: V3019 CWE-697 'as'キーワードを使用した型変換後、おそらく誤った変数がnullと比較されます。 変数「obj」、「newResolution」を確認してください。 GameViewSizesMenuItemProvider.cs 104
 private static GameViewSize CastToGameViewSize(object obj) { GameViewSize newResolution = obj as GameViewSize; if (obj == null) { Debug.LogError("Incorrect input"); return null; } return newResolution; } 

このメソッドでは、 obj変数がnullにならない状況を予測することを忘れていましたが、 GameViewSize型にキャストすることはできません。 次に、 newResolution変数はnullを取得し、デバッグ出力は生成されません。 コードの修正バージョンは次のとおりです。
 private static GameViewSize CastToGameViewSize(object obj) { GameViewSize newResolution = obj as GameViewSize; if (newResolution == null) { Debug.LogError("Incorrect input"); } return newResolution; } 

欠陥

PVS-Studio警告: V3020 CWE-670ループ内の無条件の「戻り」。 PolygonCollider2DEditor.cs 96
 private void HandleDragAndDrop(Rect targetRect) { .... foreach (....) { .... if (....) { .... } return; } .... } 

ループは1回の反復のみを実行し、その後メソッドは作業を完了します。 さまざまなシナリオが考えられます。 たとえば、 returnifブロック内、またはreturnの前のどこかにcontinueディレクティブが欠落している必要があります。 ここにエラーがない場合もありますが、コードをより理解しやすくする必要があります。

到達不能コード

PVS-Studio警告: V3021 CWE-561同一の条件式を持つ2つの「if」ステートメントがあります。 最初の「if」ステートメントにはメソッドの戻り値が含まれます。 これは、2番目の「if」ステートメントが無意味なCustomScriptAssembly.csであることを意味します179
 public bool IsCompatibleWith(....) { .... if (buildingForEditor) return IsCompatibleWithEditor(); if (buildingForEditor) buildTarget = BuildTarget.NoTarget; // Editor .... } 

2つの同一のチェック、次々。 明らかに、 buildingForEditorが true設定されている場合 、最初のメソッドは終了するため、2番目のチェックは無意味です。 buildingForEditor値がfalseの 場合 、最初のifステートメントの then-branchも2番目のifステートメントも実行されません。 修正が必要な誤った設計があります。

無条件

PVS-Studio 警告 V3022 CWE-570式 'index <0 && index> = parameters.Length'は常にfalseです。 AnimatorControllerPlayable.bindings.cs 287
 public AnimatorControllerParameter GetParameter(int index) { AnimatorControllerParameter[] param = parameters; if (index < 0 && index >= parameters.Length) throw new IndexOutOfRangeException( "Index must be between 0 and " + parameters.Length); return param[index]; } 

インデックスをチェックする条件が正しくありません-結果は常にfalseです。 ただし、 無効なインデックスがGetParameterメソッドに渡された場合、 IndexOutOfRangeException例外は引き続きスローされますが、既に戻りブロック内の配列要素にアクセスしようとしています。 確かに、エラーメッセージはわずかに異なります。 開発者が期待するようにコードが動作するためには、&&演算子の代わりに||を使用する必要があります。
 public AnimatorControllerParameter GetParameter(int index) { AnimatorControllerParameter[] param = parameters; if (index < 0 || index >= parameters.Length) throw new IndexOutOfRangeException( "Index must be between 0 and " + parameters.Length); return param[index]; } 

おそらくコピーペーストの方法論を使用しているため、Unityコードには別の正確なエラーが存在します。

PVS-Studio 警告 V3022 CWE-570式 'index <0 && index> = parameters.Length'は常にfalseです。 Animator.bindings.cs 711

また、配列インデックスをチェックするための誤った条件に関連する別の同様のエラー:

PVS-Studio 警告 V3022 CWE-570式 'handle.valueIndex <0 && handle.valueIndex> = list.Length'は常にfalseです。 StyleSheet.cs 81
 static T CheckAccess<T>(T[] list, StyleValueType type, StyleValueHandle handle) { T value = default(T); if (handle.valueType != type) { Debug.LogErrorFormat(.... ); } else if (handle.valueIndex < 0 && handle.valueIndex >= list.Length) { Debug.LogError("Accessing invalid property"); } else { value = list[handle.valueIndex]; } return value; } 

そしてこの場合、 IndexOutOfRangeExceptionのスローが可能です。 エラーを修正するには、前のコードフラグメントのように、条件で||演算子を使用する必要があります。 &&の代わりに。

ただ奇妙なコード

2つの警告は、次のコードスニペットを示しています。

PVS-Studio警告: V3022 CWE-571式 'bRegisterAllDefinitions || (AudioSettings.GetSpatializerPluginName()== "GVR Audio Spatializer") 'は常に真です。 AudioExtensions.cs 463

PVS-Studio警告: V3022 CWE-571式 'bRegisterAllDefinitions || (AudioSettings.GetAmbisonicDecoderPluginName()== "GVR Audio Spatializer") 'は常に真です。 AudioExtensions.cs 467
 // This is where we register our built-in spatializer extensions. static private void RegisterBuiltinDefinitions() { bool bRegisterAllDefinitions = true; if (!m_BuiltinDefinitionsRegistered) { if (bRegisterAllDefinitions || (AudioSettings.GetSpatializerPluginName() == "GVR Audio Spatializer")) { } if (bRegisterAllDefinitions || (AudioSettings.GetAmbisonicDecoderPluginName() == "GVR Audio Spatializer")) { } m_BuiltinDefinitionsRegistered = true; } } 

不完全なメソッドのように見えます。 なぜ彼がこの形式で残され、コードの無駄なブロックについてコメントしなかったのかは不明です。 現在、すべてのメソッドが実行しています:
 if (!m_BuiltinDefinitionsRegistered) { m_BuiltinDefinitionsRegistered = true; } 

無駄な方法

PVS-Studio警告: V3022 CWE-570式「PerceptionRemotingPlugin.GetConnectionState()!= HolographicStreamerConnectionState.Disconnected」は常にfalseです。 HolographicEmulationWindow.cs 171
 private void Disconnect() { if (PerceptionRemotingPlugin.GetConnectionState() != HolographicStreamerConnectionState.Disconnected) PerceptionRemotingPlugin.Disconnect(); } 

状況を明確にするには、 PerceptionRemotingPlugin.GetConnectionState()メソッドの宣言を見てください。
 internal static HolographicStreamerConnectionState GetConnectionState() { return HolographicStreamerConnectionState.Disconnected; } 

したがって、 Disconnect()メソッドを呼び出しても何も起こりません。

同じPerceptionRemotingPlugin.GetConnectionState()メソッドにもう1つエラーが関連付けられています。

PVS-Studio警告: V3022 CWE-570式「PerceptionRemotingPlugin.GetConnectionState()== HolographicStreamerConnectionState.Connected」は常にfalseです。 HolographicEmulationWindow.cs 177
 private bool IsConnectedToRemoteDevice() { return PerceptionRemotingPlugin.GetConnectionState() == HolographicStreamerConnectionState.Connected; } 

このメソッドの結果は次と同等です。
 private bool IsConnectedToRemoteDevice() { return false; } 

ご覧のように、警告V3022には多くの興味深いものがありました。 おそらく、もう少し時間を費やすなら、リストを増やすことができます。 しかし、先に進みましょう。

フォーマットされていません

PVS-Studio警告: V3025 CWE-685形式が正しくありません 。 「フォーマット」関数を呼び出すときに、異なる数のフォーマット項目が予想されます。 使用されない引数:インデックス。 Physics2D.bindings.cs 2823
 public void SetPath(....) { if (index < 0) throw new ArgumentOutOfRangeException( String.Format("Negative path index is invalid.", index)); .... } 

エラーはありませんが、彼らが言うように、コードは「臭い」です。 このメッセージは、おそらく「ネガティブパスインデックス{0}が無効です。 その後、単純化されましたが、 Formatメソッドのインデックスパラメーターを削除するのを忘れていました。 もちろん、これは、指定された文字列出力指定子の忘れられたパラメーターと同じではありません。つまり、 String.Format( "負のパスインデックス{0}は無効です。")という形式の構築です。 その場合、例外がスローされます。 ただし、この場合、リファクタリングの精度も必要です。 コードは次のように修正する必要があります。
 public void SetPath(....) { if (index < 0) throw new ArgumentOutOfRangeException( "Negative path index is invalid."); .... } 

部分文字列部分文字列

警告PVS-Studio: V3053過剰な表現。 部分文字列「UnityEngine」を調べます。 および「UnityEngine.SetupCoroutine」。 StackTrace.cs 43
 static bool IsSystemStacktraceType(object name) { string casted = (string)name; return casted.StartsWith("UnityEditor.") || casted.StartsWith("UnityEngine.") || casted.StartsWith("System.") || casted.StartsWith("UnityScript.Lang.") || casted.StartsWith("Boo.Lang.") || casted.StartsWith("UnityEngine.SetupCoroutine"); } 

条件内のサブストリング「UnityEngine.SetupCoroutine」の検索は、「UnityEngine」の検索がこの前に実行されるため、意味がありません。 したがって、最後のチェックを削除するか、サブストリングの正確性を明確にする必要があります。

別の同様のエラー:

警告PVS-Studio: V3053過剰な表現。 サブストリング「Windows.dll」および「Windows」を調べます。 AssemblyHelper.cs 84
 static private bool CouldBelongToDotNetOrWindowsRuntime(string assemblyPath) { return assemblyPath.IndexOf("mscorlib.dll") != -1 || assemblyPath.IndexOf("System.") != -1 || assemblyPath.IndexOf("Windows.dll") != -1 || // <= assemblyPath.IndexOf("Microsoft.") != -1 || assemblyPath.IndexOf("Windows.") != -1 || // <= assemblyPath.IndexOf("WinRTLegacy.dll") != -1 || assemblyPath.IndexOf("platform.dll") != -1; } 

サイズが重要

PVS-Studio警告: V3063 CWE-571評価される場合、条件式の一部は常にtrueです:pageSize <=1000。UNETInterface.cs 584
 public override bool IsValid() { .... return base.IsValid() && (pageSize >= 1 || pageSize <= 1000) && totalFilters <= 10; } 

許容可能なページサイズをチェックする条件が間違っています。 演算子の代わりに|| &&を使用する必要があります。 修正されたコード:
 public override bool IsValid() { .... return base.IsValid() && (pageSize >= 1 && pageSize <= 1000) && totalFilters <= 10; } 

ゼロによる除算が可能です

PVS-Studio警告: V3064 CWE-369ゼロによる潜在的な除算。 分母 '(float)(width-1)'の検査を検討してください。 ClothInspector.cs 249
 Texture2D GenerateColorTexture(int width) { .... for (int i = 0; i < width; i++) colors[i] = GetGradientColor(i / (float)(width - 1)); .... } 

この問題は、値の幅= 1をメソッドに渡すときに発生する場合があります。 メソッド自体では、これはいかなる方法でもチェックされません。 GenerateColorTextureメソッドは、パラメーター100でコード内で1回だけ呼び出されます。
 void OnEnable() { if (s_ColorTexture == null) s_ColorTexture = GenerateColorTexture(100); .... } 

したがって、まだエラーはありません。 ただし、 念のため、 GenerateColorTextureメソッドは、誤った幅の値を送信する機能を提供する必要があります。

逆説的なチェック

PVS-Studio警告: V3080 CWE-476 null参照の可能性があります。 「m_Parent」の検査を検討してください。 EditorWindow.cs 449
 public void ShowPopup() { if (m_Parent == null) { .... Rect r = m_Parent.borderSize.Add(....); .... } } 

おそらくタイプミスが原因で、このコードの実行によりn参照m_Parentの使用が保証されます。 修正されたコード:
 public void ShowPopup() { if (m_Parent != null) { .... Rect r = m_Parent.borderSize.Add(....); .... } } 

コードの後半でまったく同じエラーが発生します。

PVS-Studio警告: V3080 CWE-476 null参照の可能性があります。 「m_Parent」の検査を検討してください。 EditorWindow.cs 470
 internal void ShowWithMode(ShowMode mode) { if (m_Parent == null) { .... Rect r = m_Parent.borderSize.Add(....); .... } 

不正な検証が原因でヌルリンク経由でアクセスする可能性がある別の興味深いエラーを次に示します。

PVS-Studio警告: V3080 CWE-476 null参照の可能性があります。 「オブジェクト」の検査を検討してください。 TypeSelectionList.cs 48
 public TypeSelection(string typeName, Object[] objects) { System.Diagnostics.Debug.Assert(objects != null || objects.Length >= 1); .... } 

Unity開発者は||の誤用に関連するミスを頻繁に犯すようです。 条件で&&。 この場合、 objectsnullの場合、条件の2番目の部分(objects!= Null || objects.Length> = 1)の検証が行われ、予期しない例外がスローされます。 エラーは次のように修正する必要があります。
 public TypeSelection(string typeName, Object[] objects) { System.Diagnostics.Debug.Assert(objects != null && objects.Length >= 1); .... } 

早期無効化

PVS-Studio警告: V3080 CWE-476 null参照の可能性があります。 「m_RowRects」の検査を検討してください。 TreeViewControlGUI.cs 272
 public override void GetFirstAndLastRowVisible(....) { .... if (rowCount != m_RowRects.Count) { m_RowRects = null; throw new InvalidOperationException(string.Format("....", rowCount, m_RowRects.Count)); } .... } 

この場合、別の例外に対してメッセージ文字列が生成されると、例外(nullリンクm_RowRectsを介したアクセス)がスローされます。 コードは、たとえば次のように修正できます。
 public override void GetFirstAndLastRowVisible(....) { .... if (rowCount != m_RowRects.Count) { var m_RowRectsCount = m_RowRects.Count; m_RowRects = null; throw new InvalidOperationException(string.Format("....", rowCount, m_RowRectsCount)); } .... } 

再度検証エラー

PVS-Studio警告: V3080 CWE-476 null参照の可能性があります。 「additionalOptions」の検査を検討してください。 MonoCrossCompile.cs 279
 static void CrossCompileAOT(....) { .... if (additionalOptions != null & additionalOptions.Trim().Length > 0) arguments += additionalOptions.Trim() + ","; .... } 

条件で&演算子が使用されているため、最初の部分をチェックした結果に関係なく、条件の2番目の部分が常にチェックされます。 additionalOptions変数がnullの場合、例外のスローは避けられません。 エラーは、&の代わりに&&演算子を使用して修正する必要があります。

ご覧のように、番号V3080の警告には、非常に陰湿なエラーがあります。

遅刻

PVS-Studio警告: V3095 CWE-476 nullに対して検証される前に 'element'オブジェクトが使用されました。 行を確認:101、107。StyleContext.cs 101
 public override void OnBeginElementTest(VisualElement element, ....) { if (element.IsDirty(ChangeType.Styles)) { .... } if (element != null && element.styleSheets != null) { .... } .... } 

要素変数は、最初にヌルの不等式をチェックせずに使用されます 。 さらに、コードではさらにそのような検証が実行されます。 コードはおそらく次のように修正する必要があります。
 public override void OnBeginElementTest(VisualElement element, ....) { if (element != null) { if (element.IsDirty(ChangeType.Styles)) { .... } if (element.styleSheets != null) { .... } } .... } 

コードには、このようなエラーがさらに18個あります。 最初の10をリストします。
無効な等しいメソッド

PVS-Studio警告: V3115 CWE-684 'null'を 'Equals'メソッドに渡すと、 'NullReferenceException'になりません。 CurveEditorSelection.cs 74
 public override bool Equals(object _other) { CurveSelection other = (CurveSelection)_other; return other.curveID == curveID && other.key == key && other.type == type; } 

Equalsメソッドのオーバーロードは不注意に行われます。 パラメーターとしてnullを取得する可能性を考慮する必要があります。これは、呼び出しコードで提供されなかった例外のスローにつながる可能性があるためです。 また、例外は_otherCurveSelectionにキャストできない状況になります。 コードを修正する必要があります。 Equalsオーバーロードを実装する良い例は、 ドキュメントにあります

コードには他にも同様のエラーがあります。
そして再び、null不等式のチェックについて

PVS-Studio警告: V3125 CWE-476 nullに対して検証された後、「カメラ」オブジェクトが使用されました。 行を確認してください:184、180。ARBackgroundRenderer.cs 184
 protected void DisableARBackgroundRendering() { .... if (camera != null) camera.clearFlags = m_CameraClearFlags; // Command buffer camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, m_CommandBuffer); camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, m_CommandBuffer); } 

カメラ変数を初めて使用するときは、 nullがチェックされます 。 しかし、彼らはそれをコードで行うことを忘れています。 修正されたバージョンの形式は次のとおりです。
 protected void DisableARBackgroundRendering() { .... if (camera != null) { camera.clearFlags = m_CameraClearFlags; // Command buffer camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, m_CommandBuffer); camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, m_CommandBuffer); } } 

別の同様のエラー:

PVS-Studio警告: V3125 CWE-476 nullに対して検証された後、 'item'オブジェクトが使用されました。 行を確認:88、85。TreeViewForAudioMixerGroups.cs 88
 protected override Texture GetIconForItem(TreeViewItem item) { if (item != null && item.icon != null) return item.icon; if (item.id == kNoneItemID) // <= return k_AudioListenerIcon; return k_AudioGroupIcon; } 

エラーが発生し、場合によってはヌルリンク経由でアクセスすることになります。 最初のifブロックで条件が満たされると、メソッドが終了します。 ただし、これが発生しない場合、 アイテムリンクがゼロ以外であるという保証はありません。 コードの修正バージョン:
 protected override Texture GetIconForItem(TreeViewItem item) { if (item != null) { if (item.icon != null) return item.icon; if (item.id == kNoneItemID) return k_AudioListenerIcon; } return k_AudioGroupIcon; } 

コードにはさらに12個の同様のエラーがあります。 最初の10をリストします。
選択肢は少なかった

PVS-Studio警告: V3136 CWE-691 switchステートメントの定数式。 HolographicEmulationWindow.cs 261
 void ConnectionStateGUI() { .... HolographicStreamerConnectionState connectionState = PerceptionRemotingPlugin.GetConnectionState(); switch (connectionState) { .... } .... } 

そして、ここでPerceptionRemotingPlugin.GetConnectionState()メソッドが原因でした。 V3022の警告を調べたときに、すでにこの問題に遭遇しました。
 internal static HolographicStreamerConnectionState GetConnectionState() { return HolographicStreamerConnectionState.Disconnected; } 

メソッドは定数を返します。 非常に奇妙なコード。 細心の注意を払う必要があります。

結論


写真6


ここでやめることができると思います。さもないと、記事は退屈で長くなります。 繰り返しますが、すぐに私を襲ったエラーを引用しました。 ユニティコードには、修正が必要なより誤った、または誤った構成要素が含まれています。 難点は、発行された警告の多くが非常に物議を醸すものであり、コードの作成者だけがそれぞれの場合に正確な「診断」を行うことができるという事実にあります。

一般に、Unityプロジェクトについてはエラーが豊富であると言えますが、コードベースのサイズ(40万行)を考慮すると、すべてがそれほど悪くはありません。 それでも、著者が製品の品質を向上させるためにコード分析ツールを無視しないことを願っています。

PVS-Studioと、すべてに不注意なコードを使用してください!



この記事を英語を話す聴衆と共有したい場合は、翻訳へのリンクを使用してください:Sergey Khrenov。Unity C#ソースコードの確認

記事を読んで質問がありますか?
多くの場合、記事には同じ質問が寄せられます。 ここで回答を収集しました: PVS-Studioバージョン2015に関する記事の読者からの質問への回答 。 リストをご覧ください。

Source: https://habr.com/ru/post/J353640/


All Articles