Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Problem mit dynamischem Array (Queue)

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
31.05.2006, 18:56 Uhr
Steffen



Hallo, habe leider mal wieder ein Problem.

Und zwar habe ich folgendes Programm geschrieben (eine PriorityQueue), das einmal eine stl-list enthält (die funktioniert einwandfrei) und eine selbst geschriebene Array-Version (die den Fehler produziert).

Und zwar bekomme ich immer nach dem einfügen des 50 zigsten ELements einen Absturz mit der Meldung "Segmentation fault (core dumped)"


vielleicht findet ihr ja etwas...ich und mein Partner sind schon die ganze Zeit (erfolgos) auf der Fehlersuche.... Abgabetermin ist heute 24 Uhr

Hier das Programm (nur die ArrayPriorityQueue-Klasse):

C++:
#ifndef ARRAYPRIORITYQUEUET_H_
#define ARRAYPRIORITYQUEUET_H_

#include "QueueEmptyEx.h"

template <class T>
class ArrayPriorityQueueT
{
    int gr;                    // Größe des Arrays
    int pos;                // Position des zuletzt eingefügten Elements / Anzahl der eingefügten Elemente
    T *entries;
    
    public:
    // Konstruktoren
    ArrayPriorityQueueT():gr(50), pos(0){entries = new T[gr];};
    
    // Destruktor
    ~ArrayPriorityQueueT()
    {
        delete[] entries;
        entries = 0;
        this->gr = 0;
        this->pos = 0;
    }
    
    // Kopierkonstruktor
    ArrayPriorityQueueT(const ArrayPriorityQueueT & a)
    {
    //    cout << "Kopier-Konstruktor" << endl;
        this->gr = a.gr;
        this->pos = a.pos;
        this->entries = new T[this->gr];
        for(int i=0; i < this->gr; i++)
            *(this->entries+i) = *(a.entries+i);
    }
        
    // Methoden
    void enlarge()
    {
        T *temp;
        int z;            // Zählervariable
        
        this->gr = this->gr+50;
        temp = new T[this->gr];
        
        if(this->entries != 0)
        {
            for(z = 0; z < this->gr; z++)
                *(temp+z) = *(this->entries+z);
            
            delete[] this->entries;
        }
        
        this->entries = temp;
        
        cout << "Array wurde vergroessert: " << this->gr << endl;
    }

    void enqueue (T e)
    {
        if(this->pos >= this->gr) this->enlarge();
        *(this->entries+this->pos) = e;
//        cout << "eingefuegt: " << *(this->entries+this->pos) << endl;
        siftUp(this->pos);
        this->pos++;
    }

    T dequeue () throw(QueueEmptyEx)
    {
        T value;
        
        if(this->pos <= 0) throw QueueEmptyEx();
        value = *(this->entries+0);
        *(this->entries+0) = *(this->entries+(this->pos-1));
        this->pos--;
        siftDown(this->pos);
        
        return(value);
    }
    
    void siftUp(int i)            // i ist der Index des betroffenen Elements
    {
        int parent;
        
        while(true)
        {
            if(i == 0) break;
            parent = ((i+1)/2)-1;
            if(*(this->entries+parent) <= *(this->entries+i)) break;
            swap(parent,i);
            i = parent;        
        }
    }

    void siftDown(int n)
    {
        int i = 0;
        int children;
        
        while(true)
        {
            children = (2*i)+1;
            if(children > n) break;
            if(children+1 <= n)
            {
                if(*(this->entries+(children+1)) < *(this->entries+children))
                {
                    children = children+1;
                }
            }
            if(*(this->entries+i) <= *(this->entries+children)) break;
            swap(children, i);
            i = children;
        }
    }
    
    void swap(int a, int b)        // Vertausch die Array-Elemente der beiden übergebenen indizes
    {
        T tmp;
        
        tmp = *(this->entries+a);
        *(this->entries+a) = *(this->entries+b);
        *(this->entries+b) = tmp;    
    }

};

#endif /*ARRAYPRIORITYQUEUET_H_*/



 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
31.05.2006, 20:19 Uhr
(un)wissender
Niveauwart


Es wird von 0 angefangen zu zählen, also size == 50 -> elemente 0, ... , 49.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
31.05.2006, 20:37 Uhr
Steffen



ja, das haben wir auch berücksichtigt. Die schleifen laufen immer nur bis < this->gr.....also bis < 50...also bis 49

ich hab glaube ich den Fehler gefunden.

wenn ich die Methode enlarge() folgendermaßen ändere, dann läuft es!

C++:
   void enlarge()
    {
        T *temp;
        int z;            // Zählervariable
        
        temp = new T[this->gr+50];      //geändert
        
        if(this->entries != 0)
        {
            for(z = 0; z < this->gr; z++)
                *(temp+z) = *(this->entries+z);
            
            delete[] this->entries;
        }
        

       this->gr = this->gr+50;   // geändert

        this->entries = temp;
        
        cout << "Array wurde vergroessert: " << this->gr << endl;
    }




bin mehr oder weniger durch zufall darauf gekommen. Kann mir jemand erklären warum es so funktioniert und so wie es vorher war nicht ?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
31.05.2006, 20:45 Uhr
(un)wissender
Niveauwart


Ok, hier der wirkliche Fehler.
In enlarge this->gr zu früh gesetzt.


C++:
#include <iostream>
using namespace std;

#ifndef ARRAYPRIORITYQUEUET_H_
#define ARRAYPRIORITYQUEUET_H_

class QueueEmptyEx
{
};
    
template <class T>
class ArrayPriorityQueueT
{
    int gr;                    // Größe des Arrays
    int pos;                // Position des zuletzt eingefügten Elements / Anzahl der eingefügten Elemente
    T *entries;
    
    public:
    // Konstruktoren
    ArrayPriorityQueueT():gr(50), pos(0){entries = new T[gr];};
    
    // Destruktor
    ~ArrayPriorityQueueT()
    {
        delete[] entries;
        entries = 0;
        this->gr = 0;
        this->pos = 0;
    }
    
    // Kopierkonstruktor
    ArrayPriorityQueueT(const ArrayPriorityQueueT & a)
    {
    //    cout << "Kopier-Konstruktor" << endl;
        this->gr = a.gr;
        this->pos = a.pos;
        this->entries = new T[this->gr];
        for(int i=0; i < this->gr; i++)
            *(this->entries+i) = *(a.entries+i);
    }
        
    // Methoden
    void enlarge()
    {
        std::cout << "enlarge\n";
        T *temp;
        int z;            // Zählervariable
        
        int newSize = this->gr+50; //erstmal temporär
        temp = new T[newSize];
        
        if(this->entries != 0)
        {
            for(z = 0; z < this->gr; z++)
                *(temp+z) = *(this->entries+z);
            
            delete[] this->entries;
        }
        
         this->gr = newSize; //Hier setzen
        this->entries = temp;
        
        cout << "Array wurde vergroessert: " << this->gr << endl;
    }

    void enqueue (T e)
    {
        if(this->pos >= this->gr) this->enlarge();
        *(this->entries+this->pos) = e;
//        cout << "eingefuegt: " << *(this->entries+this->pos) << endl;
        siftUp(this->pos);
        this->pos++;
    }

    T dequeue () throw(QueueEmptyEx)
    {
        T value;
        
        if(this->pos <= 0) throw QueueEmptyEx();
        value = *(this->entries+0);
        *(this->entries+0) = *(this->entries+(this->pos-1));
        this->pos--;
        siftDown(this->pos);
        
        return(value);
    }
    
    void siftUp(int i)            // i ist der Index des betroffenen Elements
    {
        int parent;
        
        while(true)
        {
            if(i == 0) break;
            parent = ((i+1)/2)-1;
            if(*(this->entries+parent) <= *(this->entries+i)) break;
            swap(parent,i);
            i = parent;        
        }
    }

    void siftDown(int n)
    {
        int i = 0;
        int children;
        
        while(true)
        {
            children = (2*i)+1;
            if(children > n) break;
            if(children+1 <= n)
            {
                if(*(this->entries+(children+1)) < *(this->entries+children))
                {
                    children = children+1;
                }
            }
            if(*(this->entries+i) <= *(this->entries+children)) break;
            swap(children, i);
            i = children;
        }
    }
    
    void swap(int a, int b)        // Vertausch die Array-Elemente der beiden übergebenen indizes
    {
        T tmp;
        
        tmp = *(this->entries+a);
        *(this->entries+a) = *(this->entries+b);
        *(this->entries+b) = tmp;    
    }

};

#endif /*ARRAYPRIORITYQUEUET_H_*/

int main()
{
    ArrayPriorityQueueT<int> queue;
    for(int i = 0; i < 1000; ++i)
    {
        queue.enqueue(3);
    }    
}    



--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
31.05.2006, 20:47 Uhr
(un)wissender
Niveauwart


Lol ok.

*(temp+z) ist halt gr groß und nicht schon gr+50. Du greift also beim kopieren der Elemente bei der Quelle um 50 Positionen zu weit.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
31.05.2006, 21:06 Uhr
Steffen



ach ja....jetzt wo du es sagst, seh ich es auch . Unter Stress sieht man manchmal den Wald vor lauter bäumen nicht!

Aber danke, das ich jetzt wenigstens weiß was ich da durch zufall verbessert habe .

Ich entferne dann mal wieder den Code aus dem Thread....nicht das ich morgen bei jedem zweiten mein Programm laufen sehe

kann ich den Thread auch irgendwie schließen ?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
31.05.2006, 21:09 Uhr
Steffen



mhh...kann nix mehr editieren....
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
31.05.2006, 22:06 Uhr
(un)wissender
Niveauwart


Hm, soll ich ehrlich sein? Den Code wirst du nirgendwo laufen sehen, weil er nicht sonderlich gut ist. Nimm es nicht persönlich, ich vermute du bist noch in der akuten Lernphase.
Außerdem ist das nur eine nomale Queue, hat nichts mit Prioritäten zu tun. Und nun halt dich fest: der std-Header <deque> ist schon da.


Bearbeitung:

Na ja, schiftdown scheint ja was mit Prios zu machen. Normalerweise würde man hier aber eine Art binary_search_insert realisieren, mit upper- oder lowerbound.
Und zwas am besten mit einem std::deque dann hast auch die ganze Allokiererei nicht mehr.


--
Wer früher stirbt ist länger tot.

Dieser Post wurde am 31.05.2006 um 22:24 Uhr von (un)wissender editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
31.05.2006, 22:29 Uhr
Steffen



also das mit dem "nicht das ich das morgen bei jedem laufen sehe" war nicht so gemeint, dass es besonders gut sein soll ....ist mir schon klar das es proffesioneller besser und toller geht. Das ganze ist eine Hausuebung und muss morgen abgegeben werden. Da ich von einigen aus der Vorlesung weiß dass sie auch hier im Forum schauen....


Zitat:

Und nun halt dich fest: der std-Header <queue> ist schon da.



I know ....wir haben das ganze in mehreren Versonen realisiert...das war die einzigste die noch gezickt hat.


Zitat:

Nimm es nicht persönlich, ich vermute du bist noch in der akuten Lernphase.



ja, hast volkommen recht! Semester II


Danke nochmal
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
01.06.2006, 00:06 Uhr
(un)wissender
Niveauwart


Ok, macht sSnn. Das mit den Übungsaufgaben hatten wir heute schon.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: