Dynamisches Array erstellen/löschen

DCTH

Grand Admiral Special
Mitglied seit
16.03.2002
Beiträge
2.057
Renomée
3
Standort
Am Neckar
Ich ma wieder ^^

Habe da eine Übung wo man verschiedene Sortieralgorythmen testen soll.

Auch wenn es nicht Aufgabe war, so wollte ich das ganze mit einer Switch-Case Anwendung verschönern.

Also derweils läufts so ab:
1. Dynamisches Array wird mit
Code:
long int *arr=NULL;
arr = new long int[arrlen];
erstellt. (arrlen ist nen einfaches int, wird mit cin eingelesen.

2. nu gehts in die Switch-Case rein. Dort kann ich wählen zwischen "neues Array erstellen, ausgeben, sortieren und beenden"

Probleme:
Erstes neu-erstellen des Arrays geht noch, aber beim ausgeben kommen die üblichen Fantasiewerte von -323235 -376659 ...
Beim 2ten mal neu erstellen stürzt mir dann sogar das Programm ab ... sieht von euch cracks direkt ob da ein schwerer Fehler drin ist?

Danke schonmal

Insgesamt:
Code:
/******************************************************
*Programm-Name: sortier-algorithmen für arrays
*******************************************************
*Erstellungsdatum: April 2009
*******************************************************
*Beschreibung: zeitaufwand unterschiedl. algorithmen
*******************************************************
*Programmierer: xxxx
******************************************************/

#include <iostream>
#include <iomanip>
#include <conio.h>
#include <algorithm>
#include <time.h>
using namespace std;

void bubblesort(long int arr[], int len);
void arrausgabe(long int arr[], int len);

void main()
{
    long int start = 0, ende = 0, minuten = 0;
    int arrlen = 0, auswahl = 0;

                cout << "Gewünschte Array-Laenge angeben" << endl;
                cin >> arrlen;
                cout << endl;
                long int *arr=NULL;
                arr = new long int[arrlen];
                srand( (unsigned)time( NULL ) );

                    for (int i=0; i<arrlen; i++)
                    {
                        arr[i] = rand() % 10 + 0;
                        //cout << arr[i] << " " ; //nicht ausgeben, braucht ewig
                    }

    while(auswahl!=9)
    {
        cout << endl;
        cout << "Bitte Funktion wählen:" << endl;
        cout << "1 - Neues Array erstellen" << endl;
        cout << "2 - Array ausgeben (kann ab 10k sehr lange dauern)" << endl;
        cout << "3 - Bubblesort anwenden" << endl;
        cout << "9 - Beenden" << endl << endl;

        cin >> auswahl;
        cout << endl;

        switch(auswahl)
        {
        case 1:
            {
                delete arr; //löschen des arrays
                *arr = NULL; //rücksetzen des zeigers

                cout << "Gewünschte Array-Laenge angeben" << endl;
                cin >> arrlen;
                cout << endl;
                long int *arr=NULL;
                arr = new long int[arrlen];
                //srand( (unsigned)time( NULL ) );

                    for (int i=0; i<arrlen; i++)
                    {
                        arr[i] = rand() % 10 + 0;
                        //cout << arr[i] << " " ; //nicht ausgeben, braucht ewig
                    }
                    break;
            }
        case 2:
            {
                arrausgabe(arr, arrlen);
                break;
            }
        case 3:
            {
                bubblesort(arr, arrlen);
                break;
            }
        case 9:
            {
                break;
            }
        }
    }

            //arrausgabe(arr, arrlen);
            //bubblesort(arr, arrlen);

    _getch();
}

void bubblesort(long int arr[], int len)
{
    int temp=0, start, ende;

    start = clock();

    for(int i=len-1; i>0; i--)
    {  //äußere schleife

        for(int y=0; y < len-1; y++)
        {  //innere schleife

            if(arr[y] > arr[y+1])
            {  //tausch der werte
                temp = arr[y];
                arr[y] = arr[y+1];
                arr[y+1] = temp;
            }
        }
    }

    ende = clock();
    cout << endl << "Zeit in ms zum sortieren des Arrays mit Bubblesort: " << ende - start << endl;
    cout << endl << "Zeit in sec zum sortieren des Arrays: " << (ende - start)/1000.0 << endl << endl;

}

void arrausgabe(long int arr[], int len)
{
    for(int i=0; i < len; i++)
        cout << arr[i] << " ";
}
 
Ist ja einfach. ;)

Lösch mal unter "case 1" die Zeile:
long int *arr=NULL;

Außerdem muss es richtig heißen:
delete[] arr; // die eckigen Klammern kennzeichnen ein Array

Wobei letzteres nichts mit dem Absturz zu tun hat, die Redefinition des Arrays aber schon.
 
DANKE!!!!

Jetzt gehts, super, danke Dir!

Edit: Halt ned ganz, die Sache mit den neuen Zufallszahlen geht noch ned ganz ...

Edit2: es geht begrenzt ... wenn ich beim ersten mal 10 Felder wähle, beim 2ten 5, dann ma 8, dann ma 12 ... sprich kleine Änderungen der größe gehen, aber zb von 20 auf 30 bringt den Fehler.
Die "Zufallszahlen" haben dann keine werte zwischen 0 und 10, sondern sehen alle ähnlich aus: -17456 -17363 -17235 ....
Danach bringt es mir auch einen Fehler ...

Edit3: scheint allerdings auch ein rein zufälliger Fehler zu sein ... also mal kann ich Problemlos von 15 auf 30 ändern, beim nächstenmal gehts schon nicht mehr von 11 auf 12 ... sehr eigenartig das ganze.
 
Zuletzt bearbeitet:
Noch besser läuft das Program, wenn du jetzt noch die Zeile löscht:
*arr = NULL; //rücksetzen des zeigers

Die Idee mit dem Rücksetzen des Pointers ist schon richtig, aber an der Stelle wegen des linearen Programmflusses auch etwas sinnlos und der Stern vor "arr" ist ein Fehler.

Beim Bubblesort würde ich mir in einem bool merken, ob überhaupt zwei Werte getauscht wurden. Wenn nicht, kann die äußere Schleife abgebrochen werden und das Programm läuft im Durchschnitt etwas schneller.
 
Ja, die Zeile habe ich schon gelöscht, bleibt das andere Problem, das scheinbar sporadisch beim (neu)erstellen des Arrays auftritt.

a) Ein Array der selben größe wieder zu erstellen klappt scheints immer wieder (also auch neue Werte zwischen 0-10.

b) war das erste array bsp 10 Felder groß, das neue soll 40 Felder groß sein, tritt meist ein Fehler auf, der sich folgendermaßen beschreiben lässt:
-Lässt man das Array ausgeben, so sind die Werte nicht zwischen 0-10, sondern -174234 -174987 und alle ähnlich, also so wie wenn man ein Array zwar erstellen, aber nicht beschreiben würde
-ODER wie ichs eben hatte: Erstes Array 10 ist ok, zweites Array 40, auch ok, doch möchte ich nun ein neues Array erstellen, kommt die Meldung: "meinprogramm.exe hat einen Haltepunkt ausgelöst. Unterbrechen/Weiter". Parallel dazu öffnet es mir "dbgdel.ccp" und setzt den Haltepunkt in folgende Zeile:
Code:
             /* verify block type */
            _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

-ODER beim ersten mal ein Array von 10, ist ok, 2tenmal eins von 40, ist ok, 3tenmal eins von 40 gibt Fehler: "Unbehandelte Ausnahme bei 0x69e5d19a (msvcp90d.dll) in 2.11.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xfeeeff0a.". Parallel Dazu wird "xlocnum" geöffnet und hält bei folgendem Teil an (die return Zeile wäre die nächste Auszuführende Zeile):
Code:
_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, long _Val) const
		{	// put formatted long to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

Mir sagt das kaum etwas ... das erste ODER scheint auf ein Problem mit dem delete-operator hinzuweisen, das zweite sagt mir garnix ...

p.s.: Ich Arbeite mit Vista x64 Business und Microsoft Visual Studio 2008

EDIT:
ODER es kommt auch vor, dass ich das Array zuerst mehrmals mit 10 Feldern problemlos erstellen kann und mir auch über Case 2 anzeigen lassen kann. Erstelle ich es dann mit 60 Feldern, wird es noch mit richtigen Zahlen zw 0-10 gefüllt. Möchte ich es mir dann aber über Case 2 anzeigen lassen, kommen wieder die komischen Werte.

EDIT2:
Die negative Werte im Array wenn es Fehler gibt sind alle die selben, also jetzt eben zb -179602

Ich bin echt ratlos ...
 
Zuletzt bearbeitet:
Einen offensichtlichen Fehler kann ich nicht sehen, aber folgendes würde ich machen:
- statt "long int" besser nur "long" schreiben. Ist das gleiche. (Vielleicht versteht der Compiler die new Anweisung mit "long int" nicht)
- arr immer auf 0 testen (nach dem delete also auf 0 setzen; wie du es schon hattest, nur ohne Stern)
- arr nur löschen, wenn nicht 0
- arr nur neu anlegen, wenn arrlen > 0
- nicht auf das Array zugreifen, wenn arr == 0

Wenn alles nichts hilft, dann debuggen.

Den Code vor dem while in main() würde ich löschen und auswahl auf 1 setzen. Das Anfangsmenü einfach ans Ende des while()-Blocks schieben.

Also nach case 1 sieht der Code etwa so aus:
Code:
if (arr != 0) {
  delete[] arr;
  arr = 0;
}
... // arrlen einlesen
if (arrlen > 0) {
  arr = new long[arrlen];
}
 
Das, was du da machst, kann nicht funktionieren. Und es wundert mich ehrlich gesagt, dass das der Compiler überhaupt mitmacht. Die Feldgröße muss zur Übersetzungszeit feststehen, da der Compiler den Speicher dafür reservieren muss. Wenn du erst zur Laufzeit festlegen kannst, wie viele Elemente du speichern willst, musst du entsprechende Datenstrukturen wie z.B. vector nehmen.
 
Das, was du da machst, kann nicht funktionieren. Und es wundert mich ehrlich gesagt, dass das der Compiler überhaupt mitmacht. Die Feldgröße muss zur Übersetzungszeit feststehen, da der Compiler den Speicher dafür reservieren muss. Wenn du erst zur Laufzeit festlegen kannst, wie viele Elemente du speichern willst, musst du entsprechende Datenstrukturen wie z.B. vector nehmen.
Nein, offensichtlich sprechen wir von C++ und da geht das schon. ;)
 
Nein, das geht nicht. Zeig mir bitte den Standard, wo das geregelt ist. Auch in C++ sind Arrays statisch und können zur Laufzeit nicht geändert werden.

PS: Und ich habe das jetzt extra nochmal im Stroustrup nachgeschlagen.

Dann schau dir mal an wie vector implementiert ist. Natürlich geht es so ;-)

A typical vector implementation consists, internally, of a pointer to a dynamically allocated array and possibly data members holding the capacity and size of the vector. The size of the vector refers to the actual number of elements, while the capacity refers to the size of the internal array.
Dynamische Speicherallozierung ist doch nichts neues mehr und wird doch in jedem Algorithmik-Kurs gelehrt. Speicher wird dabei meist in der Dimension 2*n alloziiert, mit n Elementen gefüllt und bei unterschreiben von 1/2 n dann kontraktiert und bei erreichen von 2n Elementen expandiert. Das ist das klassische Beispiel für eine ammortisierte Kostenanalyse mit der Potentialmethode. nachzuschlagen im Cormen, Kapitel 17, Amortized Analysis: the potential method.
 
Zuletzt bearbeitet:
Dynamische Speicherallozierung ist doch nichts neues mehr und wird doch in jedem Algorithmik-Kurs gelehrt. Speicher wird dabei meist in der Dimension 2*n alloziiert, mit n Elementen gefüllt und bei unterschreiben von 1/2 n dann kontraktiert und bei erreichen von 2n Elementen expandiert. Das ist das klassische Beispiel für eine ammortisierte Kostenanalyse mit der Potentialmethode.

Du brauchst mir hier nicht die Theorie zu erklären, die kenne ich selber. Mir wäre es aber neu, dass das der Compiler macht. Denn der packt so etwas meines Wissens in das Data-Segment, und sorgt nicht für eine Allokation auf dem Heap zur Laufzeit.
 
Du brauchst mir hier nicht die Theorie zu erklären, die kenne ich selber. Mir wäre es aber neu, dass das der Compiler macht. Denn der packt so etwas meines Wissens in das Data-Segment, und sorgt nicht für eine Allokation auf dem Heap zur Laufzeit.
ist im C99 Standard spezifiziert.

Abgesehen davon: da arrays eh immer als pointer representiert werden (probier mal in einem Array der Länge 5 auf das Element 7 zuzugreifen (buffer overflow) - was einwandfrei funktioniert, aber eben nicht korrekt alloziiert ist) gibt es damit sowieso höchstens Denkprobleme ;-)
 
Zuletzt bearbeitet:
ist im C99 Standard spezifiziert.
Ah ok, der war mir neu. Anscheinend wurde das ganze da auf den Stack verlegt.

Abgesehen davon: da arrays eh immer als pointer representiert werden (probier mal in einem Array der Länge 5 auf das Element 7 zuzugreifen (buffer overflow) - was einwandfrei funktioniert, aber eben nicht korrekt alloziiert ist) gibt es damit sowieso höchstens Denkprobleme ;-)[/QUOTE]

Das hat nichts mit Zeigern zu tun, sonder schlicht und ergreifend mit der Tatsache, dass kein boundary check durchgeführt wird. Mir ist auch nicht ganz klar, was du mit "als pointer representiert" meinst.
 
Na ein Array ist im Prinzip nichts anders als eine aufsteigende Reihe von pointern. Und aus dem Grund muss eben der boundary check auch selbst implementiert werden.

intern bedeuter a das gleiche wie *[a+i]. Was man sich dabei vor Augen halten muss ist die Tatsache dass der TYP des Arrays zur Laufzeit durch den Compiler bekannt ist, somit ist i immer abhängig vom Speicherplatzbedarf des Typs.
 
Na ein Array ist im Prinzip nichts anders als eine aufsteigende Reihe von pointern. Und aus dem Grund muss eben der boundary check auch selbst implementiert werden.
Also das stimmt jetzt definitiv nicht. Zeiger und Arrays können äquivalent benutzt werden. Das hindert aber nicht daran, einen boundary check im Compiler bei Verwendung von Arrays zu implementieren.
Und "eine aufsteigende Reihe von pointern" finde ich ziemlich missverständlich ausgedrückt. Weil, ein Array ist ein Speicherbereich für eine Anzahl Elemente eines bestimmten Typs. Über die kann mit Zeigern iteriert werden.
 
Also ersteinmal ... so tief stecke ich noch nicht in der Materie drin, als dass ich mich an der Diskussion beteiligen könnte. ;D

Aber ich habe jetzt mal eine einzige Zeile auskommentiert, nämlich in meinem Case 1 die Zeile "long *arr=NULL;"
Und nu ... es funktioniert ... keine Probleme mehr (ohne Gewähr, aber erste Test liefen gut) ... warum versteh ich allerdings nicht.
Ich dachte die Zeile braucht es "standardmäßig" ...!?

Edit: Nommal der nun funktionierende Code:
Code:
/******************************************************
*Programm-Name: sortier-algorithmen für arrays
*******************************************************
*Erstellungsdatum: April 2009
*******************************************************
*Beschreibung: zeitaufwand unterschiedl. algorithmen
*******************************************************
*Programmierer: xxxx
******************************************************/

#include <iostream>
#include <iomanip>
#include <conio.h>
#include <algorithm>
#include <time.h>
using namespace std;

void bubblesort(long arr[], int len);
void arrausgabe(long arr[], int len);

void main()
{
    long start = 0, ende = 0, minuten = 0;
    int arrlen = 0, auswahl = 0;

                cout << "Gewünschte Array-Laenge angeben" << endl;
                cin >> arrlen;
                cout << endl;
                long *arr=NULL;
                arr = new long[arrlen];
                //srand( (unsigned)time( NULL ) );

                    for (int i=0; i<arrlen; i++)
                    {
                        arr[i] = rand() % 10 + 0;
                        //cout << arr[i] << " " ; //nicht ausgeben, braucht ewig
                    }

    while(auswahl!=9)
    {
        cout << endl;
        cout << "Bitte Funktion wählen:" << endl;
        cout << "1 - Neues Array erstellen" << endl;
        cout << "2 - Array ausgeben (kann ab 10k sehr lange dauern)" << endl;
        cout << "3 - Bubblesort anwenden" << endl;
        cout << "9 - Beenden" << endl << endl;

        cin >> auswahl;
        cout << endl;

        switch(auswahl)
        {
        case 1:
            {
                if(arr!=0)
                {
                    delete[] arr; //löschen des arrays
                    arr = 0;
                }

                cout << "Gewünschte Array-Laenge angeben" << endl;
                cin >> arrlen;
                cout << endl;
                //long *arr=NULL;
                arr = new long[arrlen];
                srand( (unsigned)time( NULL ) );

                    for (int i=0; i<arrlen; i++)
                    {
                        arr[i] = rand() % 10 + 0;
                        cout << arr[i] << " " ; //nicht ausgeben, braucht ewig
                    }
                    break;
            }
        case 2:
            {
                arrausgabe(arr, arrlen);
                break;
            }
        case 3:
            {
                bubblesort(arr, arrlen);
                break;
            }
        case 9:
            {
                break;
            }
        }
    }

            //arrausgabe(arr, arrlen);
            //bubblesort(arr, arrlen);

    _getch();
}

void bubblesort(long arr[], int len)
{
    int temp=0, start, ende;

    start = clock();

    for(int i=len-1; i>0; i--)
    {  //äußere schleife

        for(int y=0; y < len-1; y++)
        {  //innere schleife

            if(arr[y] > arr[y+1])
            {  //tausch der werte
                temp = arr[y];
                arr[y] = arr[y+1];
                arr[y+1] = temp;
            }
        }
    }

    ende = clock();
    //cout << endl << "Zeit in ms zum sortieren des Arrays mit Bubblesort: " << ende - start << endl;
    cout << endl << "Zeit in sec zum sortieren des Arrays: " << (ende - start)/1000.0 << endl << endl;

}

void arrausgabe(long arr[], int len)
{
    for(int i=0; i < len; i++)
        cout << arr[i] << " ";
}
 
Zuletzt bearbeitet:
Das Thema ist für den Fragenden wohl schon längst abgehakt, aber ich möchte auch einen Fall für diesen Fehler schildern. Mit folgender Konstallation habe ich denselben Fehler bei mir bekommen:

Code:
[COLOR="Blue"]typedef struct[/COLOR]
{
	// General parameters
	[COLOR="Blue"]bool[/COLOR]		bRegardLandmarks;						[COLOR="Lime"]// Whether landmarks are to be taken into consideration[/COLOR]
	BYTE		nErrorSound;							[COLOR="lime"]// Error sound identifier[/COLOR]
} LevelData;

[COLOR="blue"]class[/COLOR] LevelInfo
{
	[...]
	BYTE	GetLevel() const;
	[...]
	LevelInfo&	InitLevels(LPCSTR szName);
	[...]
[COLOR="blue"]private[/COLOR]:
	[...]
	LevelData				m_LevelData;
}

BYTE LevelInfo::GetLevel() const
{
	[COLOR="blue"][B]return[/B][/COLOR] m_LevelData.nLevel;
}

LevelInfo& LevelInfo::InitLevels(LPCSTR szName/*, [COLOR="Blue"]const[/COLOR] Wallpaper &wallpaper*/)
{
	CPSDatFile *pDatSection = [COLOR="blue"]new[/COLOR] CPSDatFile(szName);
	[...]
	LevelInfo &levelInfo = *[COLOR="blue"]new[/COLOR] LevelInfo();
[...]
	BYTE nByte;
	pDatSection->ReadValue([COLOR="Sienna"]"Level"[/COLOR], nByte, [B][COLOR="Red"]GetLevel()[/COLOR][/B]);
	[...]
	[COLOR="Blue"][B]return[/B][/COLOR] levelInfo;
}
Die Korrektur war "einfach" - habe es aber lange suchen müssen:
Code:
	pDatSection->ReadValue([COLOR="Sienna"]"Level"[/COLOR], nByte, [B]levelInfo.[/B]GetLevel());
Interessanter Weise kam der Fehler erst dann, als ich die Methode InitLevels von einer anderen Klasse in die LevelInfo-Klasse übernahm.
 
Zurück
Oben Unten