C++ Problem, delete[]array; ?

aelo

software developer
Thread Starter
Mitglied seit
01.09.2006
Beiträge
3.765
Ort
Österreich / Vlbg
Hi,

ich hab ein großes Problem, ich habe schonn alles Probiert, das Programm funktioniert ohne die delete Funktion ohne Probleme aber ich brauche es mit delete (Aufgabenstellung!)

Code:
#include <iostream>
using namespace std;

int main()
{

	int* palt;
	int* pneu;
	char status='j';
	int counter=0;
	int swap;
	int counter2;




	while(status=='j')
	{
		cout<<"Geben Sie die "<<counter+1<<". Zahl ein: ";
		cin>>swap;

[COLOR="Red"][B]		if(counter!=0)delete[]palt;[/B][/COLOR]
		palt=new int[counter+1];
		
		

			counter2=0;
			while(counter2<counter)
			{
					palt[counter2] = pneu[counter2];
					counter2++;
			}




		palt[counter2]=swap;
[COLOR="Red"][B]
		if(counter!=0)delete[]pneu; [/B][/COLOR]
		counter++;
		pneu=new int[counter];

		pneu=palt;




		cout<<"Wollen Sie eine Zahl eingeben? j/n : ";
		cin>>status;

	}
	
	
	cout<<endl<<endl;
	for(int a=0;a<counter;a++)cout<<pneu[a]<<" | ";

	return 0;
}

wenn ich die markierten beiden Zeilen auskommentiere funktioniert das Programm, so aber stürtzt es bei der Eingabe der zweiten Zahl ab!

schon mal VIELEN DANK für eure hilfe, ich bin kurz vor dem Verzweifeln :(

mfg
aelo
 
Wenn Du diese Anzeige nicht sehen willst, registriere Dich und/oder logge Dich ein.
Hi,

du hast da echt grundlegende Dinge bei der Nutzung von Zeigern nicht verstanden. Du brauchst ein verünftiges Buch, z.B.:
http://www.amazon.de/C-Kompendium-D...856047?ie=UTF8&s=books&qid=1194306948&sr=1-11

Dieses Buch ist zwar ein dicker Brocken und auch eher ein Nachschlagewerk, hast du aber genügend Ehrgeiz ist es zu packen. Alles, was du nicht verstehst, bei Google einfach nachschlagen. Oder noch zusätzlich ein Einstiegsbuch holen.

Nun zu deinem Code. Es sei gesagt, dass ich mich nur auf die Fehler im enthaltenen Code konzentriere und nicht auf den Programmierstil achte (is nicht bös gemeint, aber übe immer weiter und mit mehr Erfahrung schreibst du besseren Code - aber wie gesagt, lerne wie oben erwähnt, deine Werkzeuge richtig kennen).


Code analyse:

Code:
#include <iostream>
using namespace std;

int main()
{

	int* palt;
	int* pneu;
	char status= 'j';
	int counter = 0;
	int swap;
	int counter2;

	while(status=='j') {

		cout<<"Geben Sie die "<<counter+1<<". Zahl ein: ";
		cin>>swap;

		if(counter!=0)
			delete[] palt;

		palt=new int[counter+1];
		
		counter2=0;
		while(counter2<counter) {
			palt[counter2] = pneu[counter2];
			counter2++;
		}

		palt[counter2]=swap;

		if(counter!=0)
			delete[] pneu; // <- [COLOR="Red"]hier stürzt es im 2. Durchlauf der Schleife ab[/COLOR]

		counter++;
		pneu=new int[counter];

		pneu=palt; // <- [COLOR="Red"]dies ist der Grund für den Absturz[/COLOR]

		cout<<"Wollen Sie eine Zahl eingeben? j/n : ";
		cin>>status;

	}
	
	
	cout<<endl<<endl;

	for( int a=0; a<counter; a++)
		cout<<pneu[a]<<" | ";

	return 0;
}

Der Grund des Absturzes (rot markiert) ist, dass du versuchst den Speicherplatz freiugeben, worauf ein Zeiger zeigt. Diesen Speicherplatz hast du aber schon vorher freigegeben. Wie fragst du dich? Siehe die untere rot markierte Stelle, denn dort kopierst du NICHT den Wert des Speicherplatzes worauf palt zeigt einfach zu der entsprechenden Stelle in pneu, sondern die ADRESSE dieses Speicherplatzes weist du palt zu. D.h. wohin palt zeigt, zeigt nun auch pneu. Dementsprechend zeigt pneu auf denselben Wert wie auch palt (aber auch an DIESELBE Adresse, wo der Wert liegt - und hier ist das Problem).

Im nächsten Durchlauf löschst du palt und legst es neu an - was passiert, erkläre ich dir kurz: palt und pneu haben zuvor auf dieselbe Adresse x1 gezeigt, an der der Wert y1 abgelegt ist. Nun löschst du palt, d.h. du gibst den Speicherplatz mit der Adresse x1 frei (wo auch der Wert y1 nun freigegeben ist). D.h. widerum, dass Windows diesen Speicherplatz nach belieben ändern kann - schließlich ist es frei. Für palt wird ein neuer Speicherplatz angelegt (mit anderer Adresse), nun zeigt es woanderhin (d.h. pneu wird davon nicht beeinflusst).

Wenn du nun hinterher pneu löschst / freigibst, dann gibt es einen Absturz, denn der Speicherplatz worauf es zeigt ist schon eigentlich freigegeben - du hast ja palt vorher freigegeben, welches an dieselbe Stelle gezeigt hat. Soetwas kann Folgen haben: Du hast keine Rechte mit pneu mehr an die freigegebene Stelle zuzugreifen - bei Win 98 / Linux / auch WinXP, wenn du das Programm als Release compilierst, hättest du eventuell einfach in einen nicht reservierten Speicherplatz (im RAM) geschrieben, wo u.U. Betriebssystemdateien liegen -> System wird instabil, Systemabsturz möglich (keine Sorge, bei Neustart sollte alles wieder ok sein). Aber stell dir mal vor, deine Software ist eine Serversoftware oder Wichtigeres...

Nun, den Fehler kann man zwar beseitigen, indem man anstatt
Code:
pneu=palt;

diesen Code schreibt:

Code:
*pneu=*palt; // Kopiere Inhalt der Adresse worauf palt zeigt in den Inhalt der Adresse, worauf pneu zeigt

Jedoch wird dies nur dafür sorgen, dass das Programm an dieser Stelle nicht mehr abstürzt, aber mehr auch nicht. Das Programm wird nicht so laufen, wie du es dir wünschst. Es gibt einfach zu viel zu erzählen, warum das Programm so nicht läuft. Dies tue ich hier nicht. Die Fehler wirst du selbst erkennen, wenn du dich mehr um Grundlagen von Zeigern bzw. überhaupt von C/C++ kümmerst. Du darfst dein Engagement nicht verlieren bzw. musst immer am Ball bleiben.

Tipp:
Ich erkenne die Problematik des Programms. Du weißt nicht, wieviele Zahlen der Benutzer eingeben möchte, demnach weißt du auch nicht, wieviel Speicherplatz du reservieren sollst.

Nun, am besten Wäre, wenn du den Benutzer fragst, denn dann kannst du direkt auf Arrays setzen. Denn je weniger Zeiger, desto besser, was aber nicht heißt, dass du nicht lernen sollst mit ihnen umzugehen. Warum besser? Mit Zeigern kann man leicht Fehler machen, die zu Ausnahmefehlern führen und das gesamte Programm zum Absturz bringen können.

Wenn du den Nutzer aber nicht abfragen möchtest, dann würde ich vorschlagen, dass du zunächst einen Zeiger mit 10 Elementen erstellst (dynamische Speicherverwaltung ist leider mit Arrays an sich nicht möglich). Sind diese nach 10 Abfragen voll und der Benutzer möchte nicht aufgeben, dann erweiterst du den Speicherbereich wieder um 10 Elemente (oder eben nach einer anderen Gleichung). So brauchst du nicht in jedem Durchlauf die Inhalte umzukopieren und es spart Zeit, was sich auch im Ablauf deines Programms bemerkbar macht.

Hier ein Programm, welches die Funktion erfüllt, der du ersehnst. Schaue es dir gut an. U.U. gibt es eine elegantere Lösung:

Code:
#include <iostream>
using namespace std;

int main() {

	int size = 10;
	int* nums1 = new int[size]; // Array von Zahlen
	int* nums2 = NULL; // Ersatzarray für Erweiterungen
	int buff = 1; // Eingabepuffer
	int whichPtr = 1; // Welcher Zeiger ist aktiv, nums1 oder nums2?
	int i,j = 0; // Zeigervariable
	

	cout << "Um zu beenden >0< eingeben und >Enter< druecken." << endl << endl;
	for( i=0; true; i++ ) {

		// Zahl abfragen, prüfen, ob beenden
		cout << "Bitte " << i+1 << ".Zahl eingeben: ";
		cin >> buff;
		cin.clear();
		cin.ignore(100,'\n');

		if( buff == 0 )
			break;

		// Je nachdem in welcher Árrayzeiger aktiv ist
		if( whichPtr == 1 )
			nums1[i] = buff;
		else
			nums2[i] = buff;

		// Arrayzeigergrenzen überprüfen, u.U. erweitern
		if ( i == (size-1) ) {
			if( whichPtr == 1 ) {

				// nums2 erstellen +10 größer nums1
				nums2 = new int[size+10];

				// Array umkopieren
				for( j=0; j<size; j++ )
					nums2[j] = nums1[j];

				// Nums1 löschen
				delete[] nums1;
				nums1 = NULL;

				whichPtr = 2; // Aktuellen Zeiger umstellen
				size += 10; // size=size+10
			}
			else {

				// nums1 erstellen +10 größer nums2
				nums1 = new int[size+10];

				// Array umkopieren
				for( j=0; j<size; j++ )
					nums1[j] = nums2[j];

				// Nums2 löschen
				delete[] nums2;
				nums2 = NULL;

				whichPtr = 1; // Aktuellen Zeiger umstellen
				size += 10; // size=size+10
			}
		}
	}

	// Eingaben ausgeben
	cout << endl;
	cout << "Eingegebene Zahlen:" << endl;

	if( whichPtr == 1 )
		for ( j=0; j<i; j++ )
			cout << nums1[j] << " ";
	else
		for ( j=0; j<i; j++ )
			cout << nums2[j] << " ";

	// Zeiger löschen, wenn nicht NULL
	if( nums1 != NULL )
		delete[] nums1;
	if( nums2 != NULL )
		delete[] nums2;

	return 0;
}
 
Zuletzt bearbeitet:
Hardwareluxx setzt keine externen Werbe- und Tracking-Cookies ein. Auf unserer Webseite finden Sie nur noch Cookies nach berechtigtem Interesse (Art. 6 Abs. 1 Satz 1 lit. f DSGVO) oder eigene funktionelle Cookies. Durch die Nutzung unserer Webseite erklären Sie sich damit einverstanden, dass wir diese Cookies setzen. Mehr Informationen und Möglichkeiten zur Einstellung unserer Cookies finden Sie in unserer Datenschutzerklärung.


Zurück
Oben Unten refresh