Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   

Die mobilen Seiten von c++.de:
http://m.c-plusplus.de
Infos hier [BETA]

  
c++.de :: FAQ - C++ (auch C++0x, C++11) ::  Heap Grundlagen: new, delete und Zeigerarithmetik  
Gehen Sie zu Seite 1, 2  Weiter
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
Waldgnurpf
Mitglied

Benutzerprofil
Anmeldungsdatum: 15.05.2001
Beiträge: 29
Beitrag 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
Beitrag 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
Beitrag 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
Beitrag 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
Beitrag 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
Beitrag 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
Beitrag 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
Beitrag 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
Beitrag 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: 600
Beitrag 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.
c++.de :: FAQ - C++ (auch C++0x, C++11) ::  Heap Grundlagen: new, delete und Zeigerarithmetik  
Gehen Sie zu Seite 1, 2  Weiter
Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




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.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.