10 Möglichkeiten, Fehler in C ++ zu vermeiden

10 Möglichkeiten, Fehler in C ++ zu vermeiden - Dummies

Es ist eine unglückliche Tatsache, dass Sie mehr Zeit damit verbringen werden, nach Fehlern zu suchen und sie zu entfernen, als Sie tatsächlich damit verbringen, Ihre C ++ - Programme an erster Stelle zu schreiben. Die hier vorgeschlagenen Vorschläge können Ihnen helfen, die Anzahl der Fehler zu minimieren, die Sie in Ihre Programme einschleusen, um die Programmierung angenehmer zu gestalten.

Alle Warnungen und Fehlermeldungen aktivieren

Die Syntax von C ++ ermöglicht eine Vielzahl von Fehlerprüfungen. Wenn der Compiler auf ein Konstrukt stößt, das er nicht entziffern kann, hat er keine andere Wahl, als eine Nachricht auszugeben. Es wird versucht, eine Synchronisierung mit dem Quellcode durchzuführen (manchmal weniger als erfolgreich), aber es wird keine ausführbare Datei generiert. Dies zwingt den Programmierer, alle Fehlermeldungen zu korrigieren.

Wenn C ++ jedoch auf eine Struktur stößt, die es herausfinden kann, aber die Struktur trotzdem fischig riecht, erzeugt C ++ eine Warnmeldung. Da C ++ sich ziemlich sicher ist, dass es versteht, was Sie wollen, wird es ausgeführt und erstellt eine ausführbare Datei, so dass Sie Warnungen ignorieren können, wenn Sie möchten. In der Tat, wenn Sie wirklich nicht gestört werden möchten, können Sie Warnungen deaktivieren.

Das Deaktivieren oder anderweitiges Ignorieren von Warnungen ist eine außergewöhnlich schlechte Idee. Es ist ein bisschen wie das Herausziehen der "Check Engine" -Leuchte auf dem Armaturenbrett Ihres Autos, weil es Sie stört. Wenn man das Problem ignoriert, geht es nicht weg.

Setzen Sie einen klaren und konsistenten Codierungsstil ein

Wenn Sie Ihren C ++ - Code klar und konsistent schreiben, verbessert dies nicht nur die Lesbarkeit Ihres Programms, sondern führt auch zu weniger Codierungsfehlern. Dieser etwas überraschende Sachverhalt ergibt sich aus der Tatsache, dass unser Gehirn nur über eine begrenzte Rechenleistung verfügt.

Wenn Sie Code lesen, der sauber und ordentlich ist und einem Stil folgt, mit dem Sie vertraut sind, verbringen Sie sehr wenig Energie damit, die Syntax der C ++ - Anweisungen zu analysieren. Dadurch bleibt mehr CPU-Leistung des Gehirns übrig, um zu decodieren, was das Programm zu tun versucht und nicht wie es das macht.

Mit einem guten Codierungsstil können Sie Folgendes bequem ausführen:

  • Unterscheiden von Klassennamen, Objektnamen und Funktionsnamen

  • Verstehen, wofür die Klasse, Funktion oder das Objekt verwendet wird , basierend auf seinem Namen

  • Unterscheidet Präprozessorsymbole von C ++ - Symbolen (dh #define-Objekte sollten hervorstechen)

  • Identifiziert Blöcke von C ++ - Code auf derselben Ebene (dies ist das Ergebnis konsistenter Einrückungen)

Außerdem müssen Sie ein Standardformat für Ihre Modulheader einrichten, das Informationen zu den Funktionen oder Klassen in jedem Modul, zum Autor, zum Datum, zur Version und zum Änderungsverlauf enthält.

Alle an einem einzelnen Projekt beteiligten Programmierer sollten denselben Codierungsstil verwenden. Ein Programm, das in einem Patchwork verschiedener Codierungsstile geschrieben ist, ist verwirrend und sieht unprofessionell aus.

Den Code kommentieren, während Sie ihn schreiben

Sie können Fehler vermeiden, wenn Sie Ihren Code kommentieren, während Sie ihn schreiben, anstatt zu warten, bis alles funktioniert, und dann zurückgehen und Kommentare hinzufügen.

Die Formulierung von Kommentaren zwingt Sie dazu, eine Bestandsaufnahme dessen zu machen, was Sie gerade tun. Kurze Kommentare sind aufschlussreich, sowohl wenn Sie sie später lesen, als auch wenn Sie sie schreiben. Schreibe Kommentare, als ob du mit einem anderen, sachkundigen Programmierer sprichst.

Führen Sie mindestens einmal einen Pfad im Debugger aus

Als Programmierer müssen Sie verstehen, was Ihr Programm tut. Es reicht nicht aus, dass das Programm den erwarteten Wert ausgibt. Sie müssen alles verstehen, was Ihr Programm tut. Nichts gibt Ihnen ein besseres Gefühl dafür, was unter der Haube vor sich geht als single-stepping das Programm und führt es Schritt für Schritt mit einem guten Debugger aus (wie der mit Code:: Blocks).

Darüber hinaus benötigen Sie beim Debuggen eines Programms Rohmaterial, um ein bizarres Verhalten zu erkennen, das beim Ausführen des Programms auftreten kann. Nichts gibt Ihnen dieses Material besser als Einzelschritt durch jede Funktion, wenn sie in Betrieb genommen wird.

Schließlich, wenn eine Funktion fertig ist und bereit ist, dem Programm hinzugefügt zu werden, muss jeder logische Pfad mindestens einmal durchlaufen werden. Bugs sind viel einfacher zu finden, wenn Sie die Funktion selbst untersuchen und nicht erst, nachdem sie mit den restlichen Funktionen in den Pot geworfen wurden - bis dahin haben Sie sich neuen Programmierherausforderungen gestellt.

Begrenzen Sie die Sichtbarkeit

Die Beschränkung der Sichtbarkeit von Klasseninternalen auf die Außenwelt ist ein Eckpfeiler der objektorientierten Programmierung. Die Klasse sollte für ihren internen Zustand verantwortlich sein - wenn etwas in der Klasse vermasselt wird, dann ist es der Fehler des Klassenprogrammierers. Der Anwendungsprogrammierer sollte sich um die Lösung des Problems kümmern.

Insbesondere bedeutet eingeschränkte Sichtbarkeit, dass Datenmitglieder außerhalb der Klasse nicht zugänglich sein sollten - das heißt, sie sollten als geschützt gekennzeichnet sein. Außerdem müssen Mitgliedsfunktionen, von denen die Anwendungssoftware nichts wissen muss, ebenfalls als geschützt gekennzeichnet werden. Stellen Sie keine der Interna der Klasse mehr frei als notwendig, um die Aufgabe zu erledigen.

Verfolgen des Heapspeichers

Der Verlust des Heapspeichers ist die häufigste Quelle schwerwiegender Fehler in Programmen, die in das Feld freigegeben wurden - und gleichzeitig das schwierigste Problem beim Suchen und Entfernen. (Da diese Fehlerart so schwer zu finden und zu entfernen ist, ist sie in Programmen, die Sie kaufen, weit verbreitet.) Möglicherweise müssen Sie ein Programm stundenlang ausführen, bevor Probleme auftreten (abhängig davon, wie groß der Speicherverlust ist).

Generell sollten Programmierer den Heapspeicher immer auf der gleichen "Ebene zuweisen und freigeben. "Wenn eine Memberfunktion MyClass:: create () einen Block des Heapspeichers reserviert und an den Aufrufer zurückgibt, sollte ein Member MyClass:: release () vorhanden sein, der ihn an den Heap zurückgibt.Insbesondere sollte MyClass:: create () nicht die übergeordnete Funktion erfordern, um den Speicher freizugeben.

Wenn überhaupt möglich, sollte MyClass solche Speicherzeiger selbst im Auge behalten und sie im Destruktor löschen.

Nullen der Zeiger nach dem Löschen des Zeigers auf

Stellen Sie sicher, dass Zeiger gelöscht werden, nachdem sie nicht mehr gültig sind. Sie tun dies, indem Sie ihnen den Wert nullptr zuweisen. Die Gründe für diese Aktion werden mit Erfahrung deutlich: Sie können weiterhin einen Speicherblock verwenden, der an den Heap zurückgegeben wurde und ihn nicht einmal kennt. Ein Programm kann 99 Prozent der Zeit fehlerfrei laufen, was es sehr schwierig macht, die 1 Prozent der Fälle zu finden, in denen der Block neu zugeordnet wird und das Programm nicht funktioniert.

Wenn Sie Zeiger ungültig machen, die nicht mehr gültig sind und Sie versuchen, sie zum Speichern eines Werts zu verwenden (Sie können nichts am oder in der Nähe des Null-Speicherorts speichern), stürzt Ihr Programm sofort ab. Abstürze klingen schlecht, aber es ist nicht, wenn es ein Problem aufdeckt. Das Problem ist da; Es ist nur eine Frage, ob Sie es finden oder nicht, bevor Sie es in Produktion setzen.

Verwenden Sie Ausnahmen, um Fehler zu behandeln

Der Ausnahmemechanismus in C ++ ist dafür ausgelegt, Fehler bequem und effizient zu behandeln. Im Allgemeinen sollten Sie einen Fehlerindikator ausgeben, anstatt ein Fehler-Flag zurückzugeben. Der resultierende Code ist einfacher zu schreiben, zu lesen und zu warten. Außerdem erwarten es andere Programmierer, und Sie würden sie nicht enttäuschen wollen, oder?

Beschränken Sie die Verwendung von Ausnahmen auf echte Fehler. Es ist nicht notwendig, eine Ausnahme von einer Funktion zu werfen, die ein "nicht funktioniert" -Indikator zurückgibt, wenn dies ein Teil des täglichen Lebens für diese Funktion ist.

Destruktoren virtuell deklarieren

Vergessen Sie nicht, einen Destruktor für Ihre Klasse zu erstellen, wenn der Konstruktor Ressourcen wie Heap-Speicher reserviert, die zurückgegeben werden müssen, wenn das Objekt sein endgültiges Ende erreicht. Wenn Sie einen Destruktor erstellt haben, vergessen Sie nicht, ihn als virtuell zu deklarieren.

"Aber", sagst du, "meine Klasse erbt nichts von irgendetwas, und sie wird nicht von einer anderen Klasse unterklassifiziert. "Ja, aber es könnte in Zukunft eine Basisklasse werden. Wenn Sie keinen guten Grund haben, den Destruktor nicht virtuell zu deklarieren, dann tun Sie dies, wenn Sie die Klasse zum ersten Mal erstellen.

Bereitstellen eines Kopierkonstruktors und eines überladenen Zuweisungsoperators

Wenn Ihre Klasse einen Destruktor benötigt, benötigt sie fast sicher einen Kopierkonstruktor und einen überladenen Zuweisungsoperator. Wenn Ihr Konstruktor Ressourcen wie Heap-Speicher zuweist, wird der standardmäßige Kopierkonstruktor und Zuweisungsoperator nichts anderes bewirken, als durch die Generierung mehrerer Zeiger auf dieselben Ressourcen einen Chaos zu verursachen.

Wenn der Destruktor für eines dieser Objekte aufgerufen wird, werden die Assets wiederhergestellt. Wenn der Destruktor für die andere Kopie kommt, wird das alles vermasseln.