Top 10 Bugs in C # -Projekten für 2019

Bild 1

Grüße an alle Käferliebhaber. Das neue Jahr steht vor der Tür, also ist es Zeit, Bilanz des kommenden Jahres zu ziehen. Eine Bewertung der interessantesten Fehler, die vom PVS-Studio-Team in C # entdeckt wurden, ist traditionell für 2019 geöffnet. Bist du bereit? Dann fangen wir an.

Zehnter Platz: "Alle verwirren"


V3066 Mögliche falsche Reihenfolge der an die 'AdjustCellBorderStyle'-Methode übergebenen Argumente:' isFirstDisplayedRow 'und' isFirstDisplayedColumn '. DataGridViewComboBoxCell.cs 1934

protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { .... dgvabsEffective = AdjustCellBorderStyle( DataGridView.AdvancedCellBorderStyle, dgvabsPlaceholder, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedRow, // <= isFirstDisplayedColumn); // <= .... } 

Fehler aus dem Artikel " WinForms: Errors, Holmes ". Der Analyzer gibt an, dass bei der Übergabe von Argumenten an die Methode die letzten beiden Argumente umgekehrt wurden. Schauen Sie sich die AdjustCellBorderStyle-Deklaration an :

 public virtual DataGridViewAdvancedBorderStyle AdjustCellBorderStyle( DataGridViewAdvancedBorderStyledataGridViewAdvancedBorderStyleInput, DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { .... } 

Es sieht so aus, als hätte der Analysator recht. Oft werden einige Argumente absichtlich in umgekehrter Reihenfolge übergeben, um beispielsweise einige Variablen auszutauschen. Aber es sieht nicht so aus, als wäre das genau der Fall. Erstens sind Variablen vom Typ bool verwirrt. Zweitens sind die Namen der Methoden ebenfalls gebräuchlich: kein "Swap" oder "Reverse". Außerdem ist es nicht so schwierig, einen solchen Fehler zu machen: Die Reihenfolge der Zeilen- / Spaltenpaare wird häufig unterschiedlich wahrgenommen.

Neunter Platz: "The Infinite is near"


V3110 Mögliche unendliche Rekursion innerhalb der Methode 'TryValidateModel'. PrefixedModuleUpdater.cs 48

 public bool TryValidateModel(object model, string prefix) { return TryValidateModel(model, Prefix(prefix)); } 

Fehler aus dem Artikel " Suchen und Analysieren von Fehlern im Orchard CMS-Code ". Es wurde ein Fehler gemacht, der eine unendliche Rekursion verursacht. Um zu verstehen, wie dieser Fehler hätte auftreten können, müssen Sie sich die Überladung der TryValidateModel- Methode ansehen :

 public bool TryValidateModel(object model) { return _updateModel.TryValidateModel(model); } 

Es ist wahrscheinlich, dass im ersten Fall ein Aufruf des Formulars verwendet werden sollte:

 public bool TryValidateModel(object model, string prefix) { return _updateModel.TryValidateModel(model, Prefix(prefix)); } 

Der Code wurde kompiliert, weil _updateModel vom Typ IUpdateModel ist und die aktuelle Klasse auch die IUpdateModel- Schnittstelle implementiert.

Achte Stelle: "Versuchen, finden"


V3091 Empirische Analyse. Es ist möglich, dass das Zeichenfolgenliteral einen Tippfehler enthält: "Verwaltungsgruppen-ID". Das Wort 'Id' ist verdächtig. Konstanten.cs 36

 public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id"; // <= public const string Recurse = "Recursively list the children of the management group"; public const string ParentId = "Parent Id of the management group"; public const string GroupName = "Management Group Id"; // <= public const string DisplayName = "Display Name of the management group"; public const string Expand = "Expand the output to list the children of the management group"; public const string Force = "Force the action and skip confirmations"; public const string InputObject = "Input Object from the Get call"; public const string ParentObject = "Parent Object"; } 

Der Fehler stammte aus dem Artikel „ Azure PowerShell: Im Grunde genommen harmlos ." Der Analysator vermutete, dass die GroupName- Konstante mit einer Fehlerzeichenfolge initialisiert wurde. Es sollte wahrscheinlich so etwas wie „Management Group Name" geben. Es ist schwierig, die Kritikalität dieses Fehlers zu beurteilen, aber einzigartig selten und schwer zu erkennen.

Siebter Platz: "Nur übersehen"


V3078 Die ursprüngliche Sortierreihenfolge geht nach wiederholtem Aufruf der 'OrderBy'-Methode verloren. Verwenden Sie die 'ThenBy'-Methode, um die ursprüngliche Sortierung beizubehalten. GridModel.Selection.cs 107

 internal partial class GridModel { private void BuildCellSelectionRegions(....) { .... this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .OrderBy(c => c.RowItemInfo.LayoutInfo.Line)); } } 

Fehler aus dem Artikel " Überprüfen der Telerik-Benutzeroberfläche auf UWP, um sich mit PVS-Studio vertraut zu machen ". Durch die Wiederverwendung von OrderBy für eine bereits sortierte Sammlung geht das Ergebnis der vorherigen Sortierung verloren. Sie müssen ThenBy verwenden :

 this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line)); 

Solche Fehler werden durch Nachlässigkeit oder Unwissenheit gemacht. Ich denke, Copy-Paste ist schuld.

Sechster Platz: "Der Code ist dokumentiert", sagten sie


V3009 Es ist merkwürdig, dass diese Methode immer den gleichen Wert von 'true' zurückgibt. MaskedTextProvider.cs 1529

 public bool Remove(out int testPosition, out MaskedTextResultHint resultHint) { .... if (lastAssignedPos == INVALID_INDEX) { .... return true; // nothing to remove. } .... return true; } 

Fehler aus dem Artikel " Überprüfen des Quellcodes von .NET Core-Bibliotheken mit dem statischen Analysator von PVS-Studio ". Die Methode gibt immer true zurück . Ja, das ist ein Fehler, aber etwas anderes ist merkwürdig. Ein ausführlicher Kommentar ist der Methode beigefügt:

Entfernt das letzte Zeichen aus der formatierten Zeichenfolge. (Letztes Zeichen in virtueller Zeichenfolge entfernen). Beim Beenden enthält der Parameter out die Position, an der die Operation tatsächlich ausgeführt wurde. Diese Position ist relativ zum Teststring. Der Parameter MaskedTextResultHint out gibt weitere Informationen zum Operationsergebnis. Gibt bei Erfolg true zurück , andernfalls false .

Konzentriere dich auf den letzten Satz. Aber wer liest diese Kommentare schon? Aber im Ernst, ein solcher Fehler kann sich leicht einschleichen, zum Beispiel beim Refactoring oder Debuggen. Wir wollten die Option markieren, wenn das Ergebnis der Methode immer wahr sein wird. Nun, wir haben vergessen, alles so zurückzugeben, wie es war.

Fünfter Platz: "Indexiere mich sofort!"


V3102 Verdächtiger Zugriff auf ein Element eines ' seq' -Objekts durch einen konstanten Index innerhalb einer Schleife. XmlQueryRuntime.cs 738

 public bool MatchesXmlType(IList<XPathItem> seq, ....) { .... for (int i = 0; i < seq.Count; i++) { if (!CreateXmlType(seq[0]).IsSubtypeOf(....)) return false; } return true; } 

Fehler aus dem Artikel " Überprüfen des Quellcodes von .NET Core-Bibliotheken mit dem statischen Analysator von PVS-Studio ". Beim Durchlaufen der seq- Auflistung verwendet die for- Schleife bei allen Iterationen fälschlicherweise nur den Zugriff auf das erste Element (Index 0 anstelle von i ).

Vierter Platz: „Nur ein Dollar und nicht genug“


V3138 String-Literal enthält einen möglichen interpolierten Ausdruck. Betrachten Sie die Inspektion: e. SSPIHandleCache.cs 42

 internal static void CacheCredential(SafeFreeCredentials newHandle) { try { .... } catch (Exception e) { if (!ExceptionCheck.IsFatal(e)) { NetEventSource.Fail(null, "Attempted to throw: {e}"); } } } 

Fehler aus dem Artikel " Überprüfen des Quellcodes von .NET Core-Bibliotheken mit dem statischen Analysator von PVS-Studio ". Die Zeichenfolge "Versuch zu werfen: {e}" scheint interpoliert zu sein. Aufgrund des fehlenden $ -Zeichens wird die Zeichenfolgendarstellung der e- Ausnahme nicht in die Zeichenfolge eingesetzt. Infolgedessen wird die Zeichenfolge unverändert verwendet.

Dritter Platz: „Es gibt keinen Ausweg“


V3008 [CWE-563] Der Variablen 'this.linker.s3.region' werden nacheinander zweimal Werte zugewiesen. Vielleicht ist das ein Fehler. Zeilen prüfen: 116, 114. AWSSDK.DynamoDBv2.Net45 S3Link.cs 116

 public string Region { get { .... } set { if (String.IsNullOrEmpty(value)) { this.linker.s3.region = "us-east-1"; } this.linker.s3.region = value; } } 

Fehler aus dem Artikel " Suchen nach Fehlern im Quellcode des Amazon Web Services SDK für .NET ." Im Hauptteil des if- Blocks wurde die Rückgabe übersprungen. Infolgedessen erhält die Variable this.linker.s3.region immer einen Wert , einschließlich einer leeren Zeichenfolge und null .

Zweiter Platz: "Werden Sie in Ordnung!"


V3070 Nicht initialisierte Variable 'LANG_USER_DEFAULT' wird beim Initialisieren der Variablen 'LOCALE_USER_DEFAULT' verwendet. NativeMethods.cs 890

 internal static class NativeMethods { .... public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); .... } 

Fehler aus dem Artikel " WinForms: Errors, Holmes ". Die Reihenfolge der Initialisierung der Klassenfelder ist vertauscht. Verwenden Sie zum Berechnen des Werts des Felds LOCALE_USER_DEFAULT das Feld LANG_USER_DEFAULT , das noch nicht initialisiert wurde und den Wert 0 hat. Die Variable LANG_USER_DEFAULT wird an keiner anderen Stelle im Code verwendet. Um zu verstehen, wozu dieser Fehler führt, wurde ein Testprogramm geschrieben, das Methoden aus WinForms-Code enthält. Der Einfachheit halber wurden einige tatsächliche Konstanten durch ihre tatsächlichen Werte ersetzt:

 internal static class NativeMethods { public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(0x00, 0x01); public static int MAKELANGID(int primary, int sub) { return ((((ushort)(sub)) << 10) | (ushort)(primary)); } public static int MAKELCID(int lgid) { return MAKELCID(lgid, 0x0); } public static int MAKELCID(int lgid, int sort) { return ((0xFFFF & lgid) | (((0x000f) & sort) << 16)); } } class Program { static void Main() { System.Console.WriteLine(NativeMethods.LOCALE_USER_DEFAULT); } } 

Nach dem Start wird auf der Konsole Folgendes angezeigt: 0. Jetzt korrigieren wir den Fehler, indem wir die Deklaration der Felder LOCALE_USER_DEFAULT und LANG_USER_DEFAULT vertauschen . Das Ergebnis des Programms in dieser Form: 1024.

Erster Platz: "Vertrauen, aber überprüfen"


Mit dem ersten Platz ist es immer schwer. Es muss etwas Außergewöhnliches und sehr Interessantes geben. Anfangs habe ich für diesen Artikel mehr als zwanzig interessante Fehler ausgewählt, aber es gab nichts, was den ersten Platz unter ihnen verdient hätte. Und dann erinnerte ich mich an einen Artikel meines Kollegen Sergey Vasiliev, der einem einzigen Fehler gewidmet war. Das Schöne an diesem Fehler ist, dass er sich direkt auf den Betrieb unseres Analysators auswirkt. Wie? Dies geht bereits aus dem Titel des Artikels " Verlauf, wie PVS-Studio einen Fehler in der in ... PVS-Studio verwendeten Bibliothek gefunden hat " hervor. Auch hier wurde die Faulheit nicht gestrichen. :) Und hier schäme ich mich vollkommen und werde keine Beschreibung des Fehlers geben, sondern vorschlagen, dem Link zum Artikel zu folgen und mehr herauszufinden. Ich garantiere - es lohnt sich. Und der Artikel ist kurz.

Fazit


Ich hoffe die Fehler waren interessant, aber der Artikel wurde nicht müde. Ich erinnere Sie daran, dass Sie den PVS-Studio Analyzer jederzeit herunterladen können, um selbst nach Fehlern in Ihren eigenen Projekten und Projekten von Drittanbietern zu suchen und sich selbst, Freunden und Kollegen zufrieden zu stellen. Und lassen Sie es weniger Fehler und mehr Zeit für die Selbstverbesserung sein! :)

Hast du gelesen Herzlichen Glückwunsch zum Aufstieg ins nächste Level! In den folgenden Artikeln unseres Blogs werden die besten Fehler des Jahres 2019 in Java- und C ++ - Projekten hervorgehoben .

Bild 2




Wenn Sie diesen Artikel mit einem englischsprachigen Publikum teilen möchten, verwenden Sie bitte den Link zur Übersetzung: Sergey Khrenov. Die 10 häufigsten Fehler in C # -Projekten im Jahr 2019 .

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


All Articles