Wieso gibt "das" keinen Memoryleak?
-
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.
-
theliquidwave schrieb:
pszBla ist nun gelöscht (der char*), aber das Literal existiert noch, richtig?
Das worauf pszBla zeigt ist gelöscht (also der new char[32]). pszBla existiert so lange bis der aktuelle Scope verlassen wird. Das Literal ist von keiner dieser Aktionen betroffen:
a) Es wurde kopiert, hat also selber nichts mehr mit dem was darauf folgt zu tun.
b) Es ist ein Literal und steht fest und unveränderlich im Programm.edit: Unter Linux passiert übrigens dies, wenn man ein Literal freigeben will:
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0000000000400edc *** ======= Backtrace: ========= /lib/libc.so.6[0x2b22cda04dd6] /lib/libc.so.6(cfree+0x6c)[0x2b22cda0974c] ./a.out[0x400b3f] /lib/libc.so.6(__libc_start_main+0xfd)[0x2b22cd9adabd] ./a.out[0x400919] ======= Memory map: ======== 00400000-00402000 r-xp 00000000 09:04 917510 /home/zensiert/src/a.out 00601000-00602000 r--p 00001000 09:04 917510 /home/zensiert/src/a.out 00602000-00603000 rw-p 00002000 09:04 917510 /home/zensiert/src/a.out 010be000-010df000 rw-p 00000000 00:00 0 [heap] 2b22ccfc3000-2b22ccfe2000 r-xp 00000000 09:02 5044 /lib/ld-2.10.1.so 2b22ccfe2000-2b22ccfe6000 rw-p 00000000 00:00 0 2b22cd1e1000-2b22cd1e2000 r--p 0001e000 09:02 5044 /lib/ld-2.10.1.so 2b22cd1e2000-2b22cd1e3000 rw-p 0001f000 09:02 5044 /lib/ld-2.10.1.so 2b22cd1e3000-2b22cd2d5000 r-xp 00000000 09:02 131242 /usr/lib/libstdc++.so.6.0.13 2b22cd2d5000-2b22cd4d5000 ---p 000f2000 09:02 131242 /usr/lib/libstdc++.so.6.0.13 2b22cd4d5000-2b22cd4dc000 r--p 000f2000 09:02 131242 /usr/lib/libstdc++.so.6.0.13 2b22cd4dc000-2b22cd4de000 rw-p 000f9000 09:02 131242 /usr/lib/libstdc++.so.6.0.13 2b22cd4de000-2b22cd4f3000 rw-p 00000000 00:00 0 2b22cd4f3000-2b22cd575000 r-xp 00000000 09:02 5051 /lib/libm-2.10.1.so 2b22cd575000-2b22cd775000 ---p 00082000 09:02 5051 /lib/libm-2.10.1.so 2b22cd775000-2b22cd776000 r--p 00082000 09:02 5051 /lib/libm-2.10.1.so 2b22cd776000-2b22cd777000 rw-p 00083000 09:02 5051 /lib/libm-2.10.1.so 2b22cd777000-2b22cd78d000 r-xp 00000000 09:02 9996 /lib/libgcc_s.so.1 2b22cd78d000-2b22cd98c000 ---p 00016000 09:02 9996 /lib/libgcc_s.so.1 2b22cd98c000-2b22cd98d000 r--p 00015000 09:02 9996 /lib/libgcc_s.so.1 2b22cd98d000-2b22cd98e000 rw-p 00016000 09:02 9996 /lib/libgcc_s.so.1 2b22cd98e000-2b22cd98f000 rw-p 00000000 00:00 0 2b22cd98f000-2b22cdaf5000 r-xp 00000000 09:02 5047 /lib/libc-2.10.1.so 2b22cdaf5000-2b22cdcf4000 ---p 00166000 09:02 5047 /lib/libc-2.10.1.so 2b22cdcf4000-2b22cdcf8000 r--p 00165000 09:02 5047 /lib/libc-2.10.1.so 2b22cdcf8000-2b22cdcf9000 rw-p 00169000 09:02 5047 /lib/libc-2.10.1.so 2b22cdcf9000-2b22cdd00000 rw-p 00000000 00:00 0 7fffb0297000-7fffb02ac000 rw-p 00000000 00:00 0 [stack] 7fffb02e0000-7fffb02e1000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Abort
-
@ SeppJ: Genau so meinte ich das! Sehr schön

@ krümelkacker: Danke
Gruß
-
theliquidwave schrieb:
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?pszBla ist ein Zeiger der automatisch aufhört zu existieren, und zwar genau dann, wenn die nächste schließende }-Klammer kommt. Was Du über delete[] löschst, ist das, worauf der Zeiger zeigt, nämlich ein dynamisch angelegtes char-Array.
Das mit den String-Literale kannst Du dir so vorstellen:
#include <iostream> int main() { std::cout << "Hallo Welt!\n"; }ist im Prinzip das Gleiche wie
#include <iostream>
const char literal001[] = "Hallo Welt!\n";
int main() {
std::cout << literal001;
}
[/cpp]
Der Unterschied ist allerdings, dass das Literal in Wirklichkeit keinen Namen besitzt. Der Compiler darf auch String-Literale mehrfach wiederbenutzen, wenn er so schlau ist. Beispiel:#include <iostream> int main() { std::cout << "Hallo Welt!\n"; std::cout << "Welt!\n"; }darf von einem Compiler auch so übersetzt werden wie
#include <iostream>
const char literal001[] = "Hallo Welt!\n";
int main() {
std::cout << literal001;
std::cout << (literal001+6);
}
[/cpp]
-
Recht interessant Sepp, nur das ich davon gar nichts verstehe

Und danke für die ausführliche Erklärung @ krümelkacker
Gruß