| Autor |
Nachricht |
Waldgnurpf
Mitglied
Benutzerprofil
Anmeldungsdatum: 15.05.2001
Beiträge: 29
|
Waldgnurpf Mitglied
10:37:00 31.05.2001 Titel: |
Heap Grundlagen: new, delete und Zeigerarithmetik |
Zitieren |
Ich habe folgende 3 Fragen:
1.
Ich erstelle ein Zeiger auf ein Array im Heap.
char *pHeap = new char[500];
und lösche den Speicherplatz wieder mit
delete [] pHeap;
Nehmen wir jetzt an, in dem reservierten Array auf dem Heap befindet sich wiederum ein Zeiger auf einen neuen Bereich im Heap.
Wenn ich nun
delete [] pHeap;
ausführe, wird dann der Speicherplatz auf den der Zeiger im Array zeigt, mitgelöscht? Oder ist der weiter reserviert?
2.
char *pHeap = new char[500];
char *pZeiger = pHeap;
pHeap = "hallo"; // führt zu einem Fehler
pZeiger = "hallo"; // geht
Wieso das? Es gilt ja *pHeap == *pZeiger
3.
Kann ich mich darauf verlassen, das bei Beendung des Programmes aller Heap-Speicher wieder freigegeben wird? Oder erhalte ich diesen Speicher erst bei Reset des PC's zurück? So wäre es ja in bestimmten Ausnahmesituationen vertrebar, den Speicher nicht im Programm freizugeben.
/edit pumuckl: Titel für FAQ angepasst. |
Zuletzt bearbeitet von pumuckl am 11:16:46 03.08.2009, insgesamt 1-mal bearbeitet |
|
 |
Werbeunterbrechung
|
|
 |
void*
Mitglied
Benutzerprofil
Anmeldungsdatum: 02.05.2001
Beiträge: 671
|
void* Mitglied
11:14:00 31.05.2001 Titel: |
|
Zitieren |
1. Dieser Speicherbereich wird nicht freigegeben. Das mußt Du schon selbst machen.
2. pHeap="hallo" führt zu keinem Fehler! Du verlierst bloß den Speicher auf den pHeap zeigt.
3. Unter Betriebssystemen von Windows und co. kann man sich wohl darauf verlassen. Es gibt jedoch Ausnahmen, z.B. wenn Du globale Ressourcen von Windows reservierst, die bleiben dann wohl blockiert. Außerdem gibt es sicher Systeme wo dies nicht der Fall ist (wenn nicht jeder Prozeß seinen eigenen Adreßbereich hat oder so). Weiterhin ist das wohl einfach schlechter Stil.
------------------
Sincerely,
void*
Everything is BIGGER in TEXAS |
|
|
|
 |
Stefan Dreckmann
Mitglied
Benutzerprofil
Anmeldungsdatum: 13.07.2001
Beiträge: 10
|
Stefan Dreckmann Mitglied
19:24:00 31.05.2001 Titel: |
|
Zitieren |
zu 2.)
char *var = "Hallo"
ist doch ein Fehler und der Compiler sollte eigentlich diesen Code nicht zulassen. (Ich weiß, die meisten sind nicht so konsequent.)
Man könnte damit so etwas schreiben:
Code:
char *var = "Hallo";
var[1] = 'e';
// ... oder auch das hier:
strcpy(var, "Welt");
[/code]
Damit würde aber schreibend auf Speicher zugegriffen, der eigentlich read only ist. Zumindest Windows(NT)-Programme würden mit solchem Code aber gnadenlos abstürzen!
Richtig wäre
const char *var = "Hallo";
und nur das sollte ein Compiler auch erlauben.
zu 3.)
Es ist im allgemeinen schlechter Stil, Speicher nicht wieder freizugeben, insbesondere dann, wenn die Möglichkeit besteht, daß ein "leichtsinnig" geschriebener Programmteil wiederverwendet wird und in der neuen Umgebung dann Probleme durch Speicherlöcher verursacht.
Andererseits kann es aber auch Anwendungen geben, in denen es Sinn macht, auf das Freigeben zu verzichten, z.B. bei kleinen Tools die nur eine Datei durchsuchen (oder so...) und sich dann wieder beenden.
Wenn man den Speicher nur mit C++-Mitteln anfordert, sollte das auf aktuellen Betriebssystemen keine Probleme verursachen, d.h. das System sollte den Speicher wieder verfügbar machen, sobald das Programm beendet wird. Das c++-new() wird mit Sicherheit keinen Spezialspeicher wie z.B. shared memory belegen, bei dem man wohl besser auf korrekte Freigabe achten sollte.
Stefan.
|
|
|
|
 |
Waldgnurpf
Mitglied
Benutzerprofil
Anmeldungsdatum: 15.05.2001
Beiträge: 29
|
Waldgnurpf Mitglied
20:54:00 31.05.2001 Titel: |
|
Zitieren |
Danke.
Wieso Read-Only?
Meinst du, weil das Array so ev. zu klein deklariert ist?
Noch etwas misteröses:
char *pHeap = new char[500];
char *pZeiger = pHeap;
pHeap++; //führt zu Absturz
pZeiger++; //geht
confused...
|
|
|
|
 |
Stefan Dreckmann
Mitglied
Benutzerprofil
Anmeldungsdatum: 13.07.2001
Beiträge: 10
|
Stefan Dreckmann Mitglied
21:12:00 31.05.2001 Titel: |
|
Zitieren |
read only:
Der Compiler wird Stringliterale wie "Hallo" idR in einem speziellen Segment des Programms ablegen, auf das nur Lesezugriff erlaubt ist (zumindest unter Windows, mit anderen Systemen kenne ich mich nicht aus). Das ist ja auch naheliegend, da Stringliterale per Definition konstant sind. Wenn man nun schreibend auf diese Daten zugreift, kriegt das System nen dicken Hals und schießt das Programm ab.
Diese Zeile
pHeap++;
führt an sich bestimmt nicht zum Absturz. Ich vermute, es wird wohl eher daran liegen, daß Du danach noch ein
delete[] pHeap;
machst. Hier versucht das Laufzeitsystem dann, den Speicher, auf den pHeap zeigt wieder freizugeben und macht Ärger, da der ursprüngliche Wert des Pointers verändert wurde und nicht mit der Rückgabe von new() übereinstimmt. Versuche mal das:
char *pHeap = new char[500];
// ...
pHeap++;
// ...
pHeap--;
delete[] pHeap;
Jetzt stimmt der Zeiger wieder und delete() sollte funktionieren.
Normalerweise sollte man übrigens nicht Zeiger, die noch an delete() übergeben werden sollen auf irgend eine Weise ändern. Ist einfach sicherer....
Stefan.
|
|
|
|
 |
Waldgnurpf
Mitglied
Benutzerprofil
Anmeldungsdatum: 15.05.2001
Beiträge: 29
|
Waldgnurpf Mitglied
21:18:00 31.05.2001 Titel: |
|
Zitieren |
Alles begriffen.
thx
Und was ist wenn ich 2 Strings addieren möchte?
z.B.
const char *StringA = "hallo";
const char *StringB = "Stefan";
const char *StringA_und_StringB = StringA + StringB;
[ 04.07.2001: Beitrag editiert von: class CMarcus ] |
|
|
|
 |
Stefan Dreckmann
Mitglied
Benutzerprofil
Anmeldungsdatum: 13.07.2001
Beiträge: 10
|
Stefan Dreckmann Mitglied
21:33:00 31.05.2001 Titel: |
|
Zitieren |
Das geht nicht. Hier addierst Du Pointer, nicht den Inhalt der Strings.
Falls Du tatsächlich mit C-Strings arbeiten möchtest, mußt Du eine Funktion verwenden (und das Ziel kann natürlich nicht mehr const sein):
Code:
#include <cstring>
#include <iostream>
// oder (altes C++):
// #include <string.h>
// #include <iostream.h>
int main() {
const char *s1 = "Hallo ";
const char *s2 = "Waldgnurpf!";
char s3[100]; // nix const!!!
strcpy(s3, s1); // Kopiere s1 nach s3.
strcat(s3, s2); // Hänge s2 hinter den Inhalt von s3.
std::cout << s3 << std::endl;
return 0;
}
[/code]
Viel leichter geht das ganze aber mit der Klasse string aus der Standardbibliothek:
Code:
#include <string>
#include <iostream>
int main() {
const std::string s1 = "Hallo ";
const std::string s2 = "Waldgnurpf!";
const std::string s3 = s1 + s2; // const OK!
std::cout << s3 << std::endl;
return 0;
}
[/code]
Tja, und dann geht auch das const wieder. Diese Klassen machen das Leben *echt* einfacher.
Stefan.
|
|
|
|
 |
GoGi
Mitglied
Benutzerprofil
Anmeldungsdatum: 31.05.2001
Beiträge: 57
|
GoGi Mitglied
22:20:00 31.05.2001 Titel: |
|
Zitieren |
Zitat: Original erstellt von Waldgnurpf:
Ich habe folgende 3 Fragen:
1.
Ich erstelle ein Zeiger auf ein Array im Heap.
char *pHeap = new char[500];
und lösche den Speicherplatz wieder mit
delete [] pHeap;
Nehmen wir jetzt an, in dem reservierten Array auf dem Heap befindet sich wiederum ein Zeiger auf einen neuen Bereich im Heap.
Wenn ich nun
delete [] pHeap;
ausführe, wird dann der Speicherplatz auf den der Zeiger im Array zeigt, mitgelöscht? Oder ist der weiter reserviert?
2.
char *pHeap = new char[500];
char *pZeiger = pHeap;
pHeap = "hallo"; // führt zu einem Fehler
pZeiger = "hallo"; // geht
Wieso das? Es gilt ja *pHeap == *pZeiger
3.
Kann ich mich darauf verlassen, das bei Beendung des Programmes aller Heap-Speicher wieder freigegeben wird? Oder erhalte ich diesen Speicher erst bei Reset des PC's zurück? So wäre es ja in bestimmten Ausnahmesituationen vertrebar, den Speicher nicht im Programm freizugeben.
[Diese Nachricht wurde von Waldgnurpf am 31-05-2001 editiert.]
char *pHeap = new char[500];
char *pZeiger = pHeap; // unzulässig
pHeap = "hallo"; // führt zu einem Fehler
pZeiger = "hallo"; // absolut unzulässig!!
1.
Wenn du 2 zeiger auf die selbe variable willst dann musst du das so machen:
char *pHeap = new char[500];
char *pZeiger;
pZeiger = pHeap;
denn mit
*pZeiger = pHeap; würde pHeap in die Zieladresse von *pZeiger gescrieben, und das passiert auch beim initialisieren
2.
man kann char *mwah = "hiereinpaarzeichen";
nur beim initialisieren. danach muss man strcpy benutzten
---
trotzdem benutzte ich fast nirgends mehr char-zeiger. die std::string klasse is viel besser
|
|
|
|
 |
Waldgnurpf
Mitglied
Benutzerprofil
Anmeldungsdatum: 15.05.2001
Beiträge: 29
|
Waldgnurpf Mitglied
10:36:00 01.06.2001 Titel: |
|
Zitieren |
Bin jetzt ein wenig verunsichert. Könnt ihr kurz folgendes Beispiel kommentieren, und die Fehler oder Unsauberheiten erläutern?
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <iostream>
using namespace std;
class String
{
private:
char *Text;
public:
char* Getname()
{
return Text;
}
SetName(char * name)
{
Text = name;
}
};
int main()
{
String *pHeap = new String[5];
String *pZeiger = pHeap;
pZeiger->SetName("1");
cout << pZeiger->Getname()<< endl;
pZeiger++;
pZeiger->SetName("2");
cout << pZeiger->Getname()<< endl;
pZeiger++;
pZeiger->SetName("3");
cout << pZeiger->Getname()<< endl;
pZeiger++;
pZeiger->SetName("4");
cout << pZeiger->Getname()<< endl;
pZeiger++;
pZeiger->SetName("5");
cout << pZeiger->Getname()<< endl;
delete [] pHeap;
return 0;
}; | |
[Diese Nachricht wurde von Waldgnurpf am 01-06-2001 editiert.]
[ Dieser Beitrag wurde am 03.11.2002 um 19:49 Uhr von Dimah editiert. ] |
|
|
|
 |
C14
Mitglied
Benutzerprofil
Anmeldungsdatum: 17.08.2000
Beiträge: 601
|
C14 Mitglied
12:19:00 01.06.2001 Titel: |
|
Zitieren |
Das SetName kann Probleme geben, wenn du einfach nur den Zeiger kopierst.
z.B.
Code:
void f(String str) {
char test[]="Das gibt Probleme";
str.SetName(test);
}
void main(){
String a;
f(a);
cout<<a.GetName();
}
[/code]
test wird da nämlich, nach beenden der Funktion f wieder gelöscht.
Der Zeiger in String zeigt aber immernoch drauf. Wenn du jetzt den String verändern willst, gibts nen Ausnahmefehler, weil du im freien Speicher rumpfuschst.
Du solltest den String also am besten wirklich kopieren: Größe des übergebenen Strings ermitteln, dann Text löschen und nochal neu mit der richtigen Größe erstellen und die Zeichen kopieren.
Sonst stimmt glaub ich alles. |
|
|
|
 |
|
Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können keine Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum nicht antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
|
|
|
|
|