Ich möchte wissen, ob es möglich ist, den delete
unten angegebenen Fehler beim Kompilieren zu erkennen . Insbesondere würde ich gerne etwas über den g ++ Compiler erfahren.
ClassTypeA *abc_ptr = new ClassTypeA[100];
abc_ptr[10].data_ = 1;
delete abc_ptr; // error, should be delete []
c++
compiler
error-detection
SebGR
quelle
quelle
std::unique_ptr<ClassTypeA[]>
und dann müssen Sie nicht.Antworten:
Im Allgemeinen kann der Compiler solche Fehler nicht erkennen. Beispiel: Angenommen, der Konstruktor für eine Klasse
new TypeName[]
weist ein Datenelement mit zu , der Destruktor verwendet jedoch fälschlicherweisedelete
stattdelete[]
. Wenn der Konstruktor und der Destruktor in separaten Kompilierungseinheiten definiert sind, wie soll der Compiler beim Kompilieren der Datei, die den Destruktor definiert, wissen, dass die Verwendung nicht mit der in der separat kompilierten Datei übereinstimmt, die den Konstruktor definiert?In Bezug auf die GNU-Compiler ist dies nicht der Fall. Wie oben erwähnt, ist dies im allgemeinen Fall nicht möglich. Ein Compiler muss solche nicht übereinstimmenden neuen / gelöschten Fehler nicht erkennen, da dies ein undefiniertes Verhalten ist. UB ist die "Get out of Jail Free" -Karte des Compiler-Anbieters.
Tools wie valgrind können diese Art von Neu- / Löschfehlanpassungen erkennen und erkennen, dies jedoch zur Laufzeit. Möglicherweise gibt es ein statisches Analysetool, das alle Quelldateien untersucht, die schließlich zu einer ausführbaren Datei kompiliert werden, aber ich kenne kein solches statisches Analysetool, das diese Art von Fehler erkennt.
quelle
Sie können die entsprechenden RAII-Klassen verwenden, um
delete
. Dies ist der einzig sichere Weg, und dieser Fehler ist nur einer von vielen, denen Sie begegnen werden, wenn Sie sichdelete
selbst anrufen .Verwenden Sie immer Klassen zum Verwalten von Ressourcen mit dynamischer Lebensdauer, und das Typsystem erzwingt die korrekte Ressourcenzerstörung.
Bearbeiten: "Was ist, wenn Sie den Code prüfen und ihn nicht ändern können?" Du bist gefickt.
quelle
Dieser besondere Fehler - ja. Diese Art von Fehler allgemein: leider nein! Das würde bedeuten, den Ausführungsfluss vorherzusagen, ohne ihn tatsächlich auszuführen, und das ist für beliebige Programme nicht möglich. (Deshalb versuchen die meisten Compiler nicht einmal, einfache Fälle wie Ihr Beispiel zu erkennen.)
Daher ist die Antwort von DeadMG die richtige: Versuchen Sie nicht, es richtig zu machen, indem Sie darauf achten - menschliche Aufmerksamkeit ist fehlbar. Verwenden Sie die von der Sprache bereitgestellten Mittel und lassen Sie den Computer darauf achten.
quelle
ClassTypeA*
so, dass Sie eine Linie zwischen dem neuen und dem Lösch-if ( rand() % 2 == 1 ) abc_ptr = new ClassTypeA;
Typ einfügen können. Nichts im statischen Typsystem zeigt an, obabc_ptr
auf ein Array oder ein dynamisches Objekt oder einen Teil davon in ein anderes Objekt oder Array verweist.abc_ptr
. Wie kann sie sonst die richtige Speichermenge freigeben? Die Laufzeit weiß also, wie viele Objekte freigegeben werden müssen.Der von Ihnen angezeigte triviale Fall kann zur Kompilierungszeit erkannt werden, da sich die Instanziierung und Zerstörung des Objekts im selben Bereich befinden. Im Allgemeinen liegt das Löschen nicht im selben Bereich oder sogar in derselben Quelldatei wie die Instanziierung. Der Typ eines C ++ - Zeigers enthält keine Informationen darüber, ob er auf ein einzelnes Objekt seines Typs oder auf ein Array verweist, geschweige denn auf das Zuordnungsschema. Daher ist es im Allgemeinen nicht möglich, dies beim Kompilieren zu diagnostizieren.
Warum nicht die möglichen Sonderfälle diagnostizieren?
In C ++ gibt es bereits Tools für den Umgang mit dem Verlust dynamischer Ressourcen, die an Bereiche gebunden sind, nämlich intelligente Zeiger und Arrays höherer Ebene (
std::vector
).Auch wenn Sie die richtige
delete
Variante verwenden, ist Ihr Code nicht ausnahmesicher. Wenn der Code zwischennew[]
unddelete[]
durch einen dynamischen Exit beendet wird, wird der Löschvorgang nie ausgeführt.In Bezug auf die Laufzeiterkennung
Valgrind
leistet das Tool gute Arbeit, um dies zur Laufzeit zu erkennen. Uhr:Natürlich läuft Valgrind nicht auf allen Plattformen und es ist nicht immer praktisch oder möglich, alle Laufzeitsituationen unter dem Tool zu reproduzieren.
quelle
Einige triviale Beispiele für die Erkennung während der Kompilierung / statischen Analyse:
Auf einem RHEL7-Host mit
cppcheck 1.77 and 1.49
http://cppcheck.sourceforge.net/
Mit
clang++ 3.7.1
auf RHEL7Der Clang Static Analyzer kann auch erkennen, wenn er
std::unique_ptr
nicht bestanden wird<char[]>
https://clang-analyzer.llvm.org/
Update unten mit einem Link zu der Arbeit, die dies hinzugefügt hat, zu den Tests und einem Fehler, den ich gefunden habe.
Dies wurde hinzugefügt, um mit "reviews.llvm.org/D4661 " zu klingen .
Tests befinden sich in test / Analysis / MismatchedDeallocator-checker-test.mm
Ich habe diesen offenen Bug gefunden - bugs.llvm.org/show_bug.cgi?id=24819
quelle