Dynamische Klassen
-
chrille schrieb:
Moin,
Anfänger Frage: Warum lässt mein Compiler eine solche Kompilierung zu?
[b]NeueListe *a[2];[/b] a[0] = new NeueListe; a[1] = new NeueListe; a[2] = new NeueListe; [b]a[3] = new NeueListe;[/b]Müsste es bei a[3] keinen Fehler geben? Danke für die Antworten.
Chrille
Weil das ein Laufzeitfehler (wenn überhaupt) ist.
-
Im übrigen ist
a[2]schon falsch. In Deinem Array gibt es nur zwei gültige Einträge, nämlich
a[0]und
a[1]
-
chrille schrieb:
Anfänger Frage: Warum lässt mein Compiler eine solche Kompilierung zu?
Der schützt dich zwar vor einigem, aber nicht vor allem - zum Beispiel nicht vor Dummheit
Es gibt allerdings durchaus Compiler, die da statische Checks drin haben, die sowas erkennen. Clang dürfte da meckern...
-
Belli schrieb:
Im übrigen ist
a[2]schon falsch. In Deinem Array gibt es nur zwei gültige Einträge, nämlich
a[0]und
a[1]Falsch ist falsch ausgedrückt. Der Standard (hab ich grad nachgelesen im C-Standard) kategorisiert das als "undefiened behaviour", also undefieniertes Verhalten.
D.H, das nicht vorgeschrieben ist was passiert.
-
Du hast ein Array mit 2 Elementen definiert, greifst aber mit (z.B. a[2]) außerhalb des definierten Arrays-Speicherbereiches zu und das ist UB.
Im besten Fall erhältst du vom Compiler eine Warnung.
Im zweitbesten Fall erhältst du zur Laufzeit einen Fehler.
Im schlimmsten Fall erhältst du überhaupt keine Fehler/Warnung und schreibst/liest auf Speicher, der anderweitig Verwendung findet.
-
Wutz schrieb:
Im schlimmsten Fall erhälst du überhaupt keine Fehler/Warnung und schreibst/liest auf Speicher, der anderweitig Verwendung findet.
Ja, genau das passiert hier offenbar. Ich war irritiert, dass während der Laufzeit kein Fehler ausgegeben wird, und man den undefinierten Bereich einfach so verwenden kann. Danke für eure Antworten.

-
chrille schrieb:
Ich war irritiert, dass während der Laufzeit kein Fehler ausgegeben wird, und man den undefinierten Bereich einfach so verwenden kann. Danke für eure Antworten.

Im Gegensatz zu gewissen anderen Sprachen, geht C++ davon aus, dass der Programmierer weiß was er tut und verschwendet daher keine Zeit damit, zur Laufzeit ständig nachzuschauen, ob die Kinder auch alle brav im Bett sind.

-
IrgendeinName schrieb:
Belli schrieb:
Im übrigen ist
a[2]schon falsch. In Deinem Array gibt es nur zwei gültige Einträge, nämlich
a[0]und
a[1]Falsch ist falsch ausgedrückt. Der Standard (hab ich grad nachgelesen im C-Standard) kategorisiert das als "undefiened behaviour", also undefieniertes Verhalten.
D.H, das nicht vorgeschrieben ist was passiert.
Ach so, das ist natürlich was anderes, dann ist es ja doch richtig.
-
chrille schrieb:
[b]NeueListe *a[2];[/b] a[0] = new NeueListe; a[1] = new NeueListe; a[2] = new NeueListe; [b]a[3] = new NeueListe;[/b]Müsste es bei a[3] keinen Fehler geben?
a[2] ist ja auch schon falsch. Mit dem einen oder anderen "static analysis" tool, würde man den Fehler wohl finden. Vielleicht können das die Compiler auch schon auf hoher Warnstufe. Wenn du aber darauf bestehst, dass zur Laufzeit solche Fehler automatisch erkannt werden, dann ist C++ nicht die richtige Sprache für dich.
In gewissen Grenzen ist aber eine optionale Prüfung (z.B. für den Debug-Modus) typischerweise möglich. Du musst nur stattdessen benutzerdefinierte Typen verwenden, die solche Debug-Modi anbieten. Rohe C-Arrays tun das nicht. Aber eine gescheite Implementierung der Standardbibliothek bietet solche Debug-Modi an, bei der dann
std::array<NeueListe*,2> a; a[0] = new NeueListe; a[1] = new NeueListe; a[2] = new NeueListe; // hier im Debug-Modus ein out-of-bounds-Check zur Laufzeit zu erwarten istAm besten guckste mal in deine Compiler-Doku rein, ob es sowas gibt, und wenn ja, wie man das aktiviert.
Außerdem solltest du mal nach RAII googeln. Delegiere die Verantwortung zur Freigabe von Resourcen möglichst früh von dir weg. In diesem Fall könnte dir ggf. ein unique_ptr helfen:
std::array<std::unique_ptr<NeueListe>,2> a; a[0].reset(new NeueListe); a[1].reset(new NeueListe);Der "Besitz" deiner dynamisch erzeugten Objekte geht an die unique_ptr-Objekte über. Die kümmern sich dann schon um die Freigabe. So kann man Speicherlecks ausschließen. In C++ ist sowas sehr wichtig. Auch wenn du irgendwo ein delete stehen hast, kommst du da vielleicht nicht mehr hin, wenn zwischendurch eine Ausnahme fliegt oder sowas...
-
Du musst verstehen, dass, wenn du auf Zeiger oder Arrays den Index-Operator anwendest, du eigentlich nur eine kürzere Schreibweise für etwas anderes nutzt:
Angenommen
arrsei als ein echtes Array oder als Zeiger deklariert, undiist ein integraler Skalar, dann istarr[i]exakt dasselbe wie
*(arr + i) //Also nichts anderes als Zeigerarithmetik. Hier kommt wieder das array-pointer decay ins Spiel.Und hier ist das Problem: darauf zu achten, dass der Index
i(oder ganz einfach die Adresse die man im Endeffekt deferenziert) "gültig" ist, ist die Aufgabe des Programmierers. Dadurch verschnellert sich der Programmablauf.Was man hier auch sieht, ist die Tatsache, dass
isemantisch gesehen auch eine negative Zahl sein kann. Dem Compiler ist das egal.