Wieso gibt "das" keinen Memoryleak?
-
Also eine Allokation und Erweiterung eines fixen Arrays kann nicht scheitern, weil es einfach nicht geht. Ist das dann ein Vorteil eines fixen Arrays?
Je nach Anwendungsfall, ja.
Ein Smart ist sicher auch sicherer als ein Ferrari, weil ich damit nicht mit 300 Sachen gegen die Wand fahren kann.
Wenn man hauptsächlich im Innenbereich von Großstädten fährt, braucht man keine 300 km/h Endgeschwindigkeit, dafür die bessere Parkplatzwahrscheinlichkeit. Wenn ich also tatsächlich kein dynamisches Array brauche, dann verzichte ich gerne auf eine zusätzliche Fehlerquelle.
-
theliquidwave schrieb:
Das ist dann wohl auch der Grund, warum der Stack innerhalb von großen Schleifen nicht so gerne benutzt wird
Vor allem bei Rekursionen mit hoher Tiefe kommt man mit dem Stack mitunter schnell in Bedrängnis...
-
Tyrdal schrieb:
Wenn ich also tatsächlich kein dynamisches Array brauche, dann verzichte ich gerne auf eine zusätzliche Fehlerquelle.
Und wenn ich eins brauche nehm ich n std::vector<T> und hab das dynamische Array mit automatischer Speicherverwaltung und ohne besagte Fehlerquelle.
-
Nein, mit besagter Fehlerquelle. Größenänderungen haben bei std::vector mit dem Heap zu schaffen und können daher schiefgehen. Ich hab nix gegen vector, aber daß Allokation auf dem Heap vorkommen kann ein Nachteil sein.
-
Tyrdal schrieb:
Nein, mit besagter Fehlerquelle. Größenänderungen haben bei std::vector mit dem Heap zu schaffen und können daher schiefgehen. Ich hab nix gegen vector, aber daß Allokation auf dem Heap vorkommen kann ein Nachteil sein.
Was passiert eher: Dass eine Heapallokation schiefgeht und eine handlebare Exception fliegt oder dass einem das Programm um die Ohren fliegt weil man ein vergleichbar großes Array auf dem Stack anlegen wollte?
-
Was ist wenn man die Wahrscheinlichkeit des Schiefgehens auf 0% beschränken möchte und der Stack berechenbar ist?
-
Tyrdal schrieb:
Wenn ich also tatsächlich kein dynamisches Array brauche, dann verzichte ich gerne auf eine zusätzliche Fehlerquelle.
Wofür es auch std::tr1::array gibt, womit man die Fehlerquellen im Umgang mit C-Arrays reduziert...
-
Tyrdal schrieb:
Was ist wenn man die Wahrscheinlichkeit des Schiefgehens auf 0% beschränken möchte und der Stack berechenbar ist?
Das ist doch der seltene Ausnahmefall. Mann kann sich immer Fälle konstruieren, wo das schlechtere plötzlich das bessere ist. Um beim Auto zu bleiben: früher gab es auch Argumente gegen den Sicherheitsgurt. Da kann man im Notfall dran hängen bleiben und dadurch nicht schnell genug aussteigen.
Wir diskutieren doch hier gerade den sparsamen Umgang mit dem Stack. Der Stack ist deutlich eingeschränkter als der Heap. Vor allem kann ich auf einen Stacküberlauf eigentlich nicht reagieren. Auf einen std::bad_alloc-Exception sehr wohl. Will ich zuverlässige Programme, sollte ich für irgendwie relevante Datenmengen den Heap bevorzugen.
Wenn ich keinen dynamischen Puffer brauche, dann nehme ich trotzdem einen std::vector und verändere die Grösse halt nicht.
-
Deswegen schrieb ich ja auch "je nach Anwendungsfall". Richtig lesen hilft.
Wenn ich keinen dynamischen Puffer brauche, dann nehme ich trotzdem einen std::vector und verändere die Grösse halt nicht.Kann man machen, finde da aber std::tr1::array passender.
-
Tyrdal schrieb:
Wenn ich keinen dynamischen Puffer brauche, dann nehme ich trotzdem einen std::vector und verändere die Grösse halt nicht.Kann man machen, finde da aber std::tr1::array passender.
Was dann auch wieder eine Entscheidungsfrage zwischen Heap und Stack ist. tr1::arrays liegen IIRC komplett auf dem Stack.
-
pumuckl schrieb:
tr1::arrays liegen IIRC komplett auf dem Stack.
Oder besser: Die Elemente sind Subobjekte von tr1::array. Natürlich kann ich auch schreiben
std::tr1::array<int,10> *p = new std::tr1::array<int,10>; delete p;
-
@pumuckl Klar das std::tr1::array macht nur ein Wrapper um nen array drum. Ich hab aber meist nur sehr kleine arrays, wenn die Größe vorher feststeht. Bei großen ist der Heap in den meisten Fällen besser. Soweit liegen unsere Meinungen nicht auseinander.

-
Viel mehr als Speicher auf Heap oder Stack anfordern können die ganzen Bibliotheken etc. ja eh nicht, bringen also keine neuen Vor- oder Nachteile.

-
Hi.
Auch wenn ich dieses alte Thema nochmal aufgreife...
Mir ist unklar, ob folgendes wirklich richtig ist:
Wenn ich eine Klasse habe, welche eine Membervariablechar szBla[32];hat, und ihr im Code dann etwas zuweise:void CKlasse::setString() { strcpy(this->szBla, "roflsdbjndfjbhdnfl"); }Wenn ich die Klasse lösche, ist dann der String auch weg?
Ist das so richtig, also dass der String dauerhaft bestehen bleibt (also ab dem Aufruf von setString bis zum löschen der Klasse)?Gruß
-
theliquidwave schrieb:
Wenn ich die Klasse lösche, ist dann der String auch weg?
Ich nehme mal an, mit Klasse meinst du eine Instanz der Klasse, auch Objekt genannt.
szBlaist dann weg, wenn du das Objekt löscht (es sei denn,szBlaiststatic)."roflsdbjndfjbhdnfl"bleibt.Ist das so richtig, also dass der String dauerhaft bestehen bleibt (also ab dem Aufruf von setString bis zum löschen der Klasse)?
szBlaexistiert ab dem Konstruktoraufruf und bleibt bis zum destruktoraufruf. setString ändert nur den Inhalt."roflsdbjndfjbhdnfl"ist ein Literal, das irgendwo im Programmcode steht und unabhängig von allen Einflüssen existiert.
-
theliquidwave schrieb:
Hi.
Auch wenn ich dieses alte Thema nochmal aufgreife...
Mir ist unklar, ob folgendes wirklich richtig ist:
Wenn ich eine Klasse habe, welche eine Membervariablechar szBla[32];hat, und ihr im Code dann etwas zuweise:void CKlasse::setString() { strcpy(this->szBla, "roflsdbjndfjbhdnfl"); }Wenn ich die Klasse lösche, ist dann der String auch weg?
Ist das so richtig, also dass der String dauerhaft bestehen bleibt (also ab dem Aufruf von setString bis zum löschen der Klasse)?Gruß
Klassen werden nicht gelöscht, nur die Objekte. Das ist ein Unterschied.
Und ja, das Array szBla des Objektes wird gelöscht, wenn das Objekt gelöscht wird. Wobei gelöscht nur heißt, dass der Speicher freigegeben wird, die Zeichen stehn dann vermutlich noch ne Weile an der Stelle im Speicher, bis der Speicher wieder benutzt wird.
Der Hardcodierte C-String "roflsdbjndfjbhdnfl" steht im Code-Segment und zwar von programmstart bis Programmende.PS: strcpy ist PFUI

-
Also ist es genau das gleiche Verhalten wie mit
char *pszBla;? Dort bleibt das Literal ja auch für immer bestehen, aber ich kann es halt kopieren, stimmts?(Was passiert eigentlich, wenn man auf ein Literal ein
delete[]anwendet?)Gruß
-
theliquidwave schrieb:
Also ist es genau das gleiche Verhalten wie mit
char *pszBla;?Kannst du die Frage präziser stellen? Ich möchte nicht einen 4-Seiten Thread nach dem passenden Codeschnipsel durchsuchen. Generell gilt: Pointer werden beim Zerstören eines Objekts wie alle Membervariablen zerstört. Das gilt aber nicht für das worauf der Pointer zeigt! Das muss man selber machen (z.B mit delete im Destruktor), falls das Objekt auf das gezeigt wird, ebenfalls zerstört werden soll. Andernfalls bleibt das Objekt auf das gezeigt wird bestehen.
(Was passiert eigentlich, wenn man auf ein Literal ein
delete[]anwendet?)Probiers doch mal aus. Keine Angst, dein Computer wird nicht explodieren (obwohl dieses Verhalten durchaus mit dem Standard vereinbar wäre).
-
char *pszBla = new char[32]; strcpy(pszBla, "das hier ist ja auch ein literal"); // ... delete[] pszBla; // pszBla ist nun gelöscht (der char*), aber das Literal existiert noch, richtig?
-
theliquidwave schrieb:
Also ist es genau das gleiche Verhalten wie mit
char *pszBla;?Was genau meinst Du? Ein Zeiger ist kein Array und ein Array ist kein Zeiger. Das ist ein wichtiger Unterschied.
theliquidwave schrieb:
Dort bleibt das Literal ja auch für immer bestehen, aber ich kann es halt kopieren, stimmts?
String-Literale haben immer eine statische Lebensdauer (existieren schon bevor die main läuft oder andere dynamische Initialisierer und bleiben solange da, bis das Programm beendet worden ist) und stehen irgendwo im Speicher. Das ist unabhängig davon, was Du mit dem Literal anstellst.
theliquidwave schrieb:
Was passiert eigentlich, wenn man auf ein Literal ein
delete[]anwendet?Was da genau passieren soll steht nirgens definiert. Das fällt unter "Undefiniertes Verhalten". Unter Linux schmiert dann das Programm ab, wenn ich mich richtig erinnere. Kannst Du ja mal ausprobieren. Aber wie gesagt, kannst Du Dich auf keine bestimmtes Verhalten verlassen.