Problem mit einer verketteten Liste
-
Hallo Leute,
ich und meine Semester-Crew, wir haben da ein kleines Problem mit dem untenstehenden Modul. Unser Programm läuft einfach net so, wie wir uns das vorstellen, denn z.b. beim Speichern der Akten bricht das Programm ab mit nem core dump.
Wir brüten nun schon seit ner woche fast jeden Tag an dem Dingens und bekommens einfach net auf die Reihe...
Vielleicht hat ja jmd von euch ne idee, wo das Problem liegen könnte.
Achtung: es geht hier eigentlich nur um eine doppelt verkettete Liste.Um jeden Vorschlag sind wir dankbar...
Gruss, chefkoch
PS: Kommentare sind alle vom Prof.
Hier das Modul:
// kette.cpp #include <string> #include <cstdlib> using namespace std; #include "kette.h" using namespace chained_list; // streng geheim namespace { // Kettenelement, entspricht einer Akte struct Node { // Aktennummer unsigned number; // Akteninhalt string text; // Zeiger auf nächsten rechten Nachbarn Node *next; //Zeiger auf das vorherige Element der Liste Node *prev; }; // Zeiger auf Startelement und aktuelles Element // Nullzeiger bedeuten nicht vorhandene Kette Node *start = 0, *current = 0; // finde den linken Nachbarn des aktuellen Elementes // Eingabe: -- // Rückgabe: Zeiger auf linken Nachbarn Node *findPredecessor(void) { // Zeiger für die Suche //Node *ptr; // am linken Ende anfangen //ptr = start; // solange der rechte Nachbar nicht das aktuelle Element ist //while (ptr->next != current) //{ // gehe zum nächst rechten Nachbarn //ptr = ptr->next; //} // Zeiger auf linken Nachbarn zurückgeben //return ptr; return current->prev; } } // namespace // streng öffentlich namespace chained_list { // Konstruktor für verkettete Liste // Eingabe: -- // Rückgabe: -- void chainDefine(void) { // gibt es etwa schon eine verkettete Liste??? if (start != 0) { // böser Klient exit(1); } // Startelement anlegen start = new Node; // Endelement anlegen start->next = new Node; // Endelement kennzeichnen start->next->next = 0; //Zeiger auf start start->next->prev = start; // aktuelles Element ist Startelement // Kennzeichen für existierende aber leere Kette current = start; } // Destruktor für verkettete Liste // Eingabe: -- // Rückgabe: -- void chainDelete(void) { // gibt es überhaupt eine Kette??? if (start == 0) { // der Klient ist ein Scherzkeks exit(1); } // löschen der Elemente von links nach rechts current = start; // solange es einen rechten Nachbarn gibt while (current != 0) { // gehe dahin current = current -> next; // lösche das ursprüngliche Element delete start; // alter rechter Nachbar ist neuer linker Rand start = current; } // Kette existiert nicht mehr start = current = 0; } // mache linken Nachbarn zum aktuellen Element // Eingabe: -- // Rückgabe: true, wenn es linken Nachbarn gibt, sonst false bool moveBack(void) { // ist linker Nachbar das Endelement? if (current->next->prev == 0) { // ja, aktuelles Element bleibt return false; } // nein, linker Nachbar wird aktuelles Element current = current->prev; return true; } // mache rechten Nachbarn zum aktuellen Element // Eingabe: -- // Rückgabe: true, wenn es rechten Nachbarn gibt, sonst false bool moveForth(void) { // ist rechter Nachbar das Endelement? if (current->next->next == 0) { // ja, aktuelles Element bleibt return false; } // nein, rechter Nachbar wird aktuelles Element current = current->next; return true; } // neues Element rechts vom aktuellen einfügen und zum neuen aktuellen Element machen // Eingabe: number - Aktennummer des neuen Elementes // text - dessen Inhalt // Rückgabe: -- void insertNode(unsigned number, string text) { // Zeiger auf neues Element Node *ptr; // neues Element erschaffen ptr = new Node; // Aktennummer einlesen ptr->number = number; // Akteninhalt einlesen ptr->text = text; // rechter Nachbar ist rechter Nachbar vom aktuellen Element ptr->next = current->next; //linker Nachbar current->next = ptr; //Zeiger auf linke Nachbarn ptr->prev = ptr->next->prev; //Zeiger auf neues Element ptr->next->prev = ptr; // neues ist nun das aktuelle Element current = current->next; } // aktuelles Element löschen // Eingabe: -- // Rückgabe: -- void deleteNode(void) { // Suchzeiger Node *ptr; // ist Kette leer? if (current == start) { return; } // linken Nachbarn suchen ptr = findPredecessor(); // aktuelles Element ausgliedern ptr->next = current->next; // aktuelles Element löschen delete current; // linker Nachbar neues aktuelles Element current = ptr; // es sei denn, linker Nachbar wäre Startelement und Kette nicht leer if (current == start && current->next->next != 0) { // dann doch besser zum rechten Nachbarn des Startelementes current = current->next; } } // Element auslesen // Eingabe: -- // Rückgabe: number - Aktennummer des aktuellen Elements // text - dessen Akteninhalt // true, wenn Kette nicht leer ist, sonst false bool readNode(unsigned &number, string &text) { // ist Kette leer? if (current == start) { // ja, number und text haben keine sinnvolle Bedeutung return false; } // Aktennummer auslesen number = current->number; // Akteninhalt auslesen text = current->text; // number und text haben sinnvolle Bedeutung return true; } // aktuelles Element ändern // Eingabe: number - neue Aktennummer // text - neuer Akteninhalt // Rückgabe: true, wenn es aktuelles Element überhaupt gibt bool writeNode(unsigned number, string &text) { // ist Kette leer? if (current == start) { // ja, kein Element geändert return false; } // Aktennummer ablegen current->number = number; // Akteninhalt ablegen current->text = text; // Erfolg anzeigen return true; } } // namespace data chain
-
Hallo,
//function deleteNode(): // linken Nachbarn suchen ptr = findPredecessor(); // aktuelles Element ausgliedern ptr->next = current->next; // aktuelles Element löschen delete current; // linker Nachbar neues aktuelles Element current = ptr;
current->next->prev zeigt immernoch auf den freigegebenen Speicherbereich, wenn
ich das hier richtig sehe. Bevor du current loeschst, muesste imho noch ein
current->next->prev = ptr; hin.mfg
v R
-
function deleteNode(): // linken Nachbarn suchen ptr = findPredecessor(); // aktuelles Element ausgliedern ptr->next = current->next; //also hier rein? current->next->prev = ptr; // aktuelles Element löschen delete current; // linker Nachbar neues aktuelles Element current = ptr;
So meinste, ne?
Gute Idee, aber wenn ich speichern will, also die Akten in eine *.txt reinschreiben will, bekomm ich noch immer ein core dump...Greetz
-
Ja so dachte ich und zwar weil, wenn current->next->prev immernoch auf den
Speicherbereich verweist, welcher freigegeben worden ist und man nun auf
current->next->prev zugreift, kommt es zu einem segfault.Wenn es das nicht war, kommst du ums debuggen nicher herum. Alternativ kannste
auch mal strace nutzen, falls du unter Linux/*BSD arbeitest.mfg
v R
-
hmm... stimmt, was du meinst...
Hab das ma verbessert, bekomme aber noch immer ein core dump als segfault, wenn ich speichern will...
ich benutze cygwin unter win, demnach g++ auf der Konsole.werd ma weiter forschen und wenn ichs hab, dann poste ichs hier rein, fals es von Interesse ist...
Gruss und besten Dank