2017-03-20 9 views
-2

ich eine doppelt verkettete Liste zu schaffen, und ich bekam einen seltsamen Fehler, verbrachten Stunden, um es zu debuggen, aber nicht so tun konnte, versucht, einen Online-Debugger und auch die nichtdoppelt verknüpften Liste „nicht behandelte Ausnahme“ Fehler

halfen

das Programm nicht kompiliert und ausgeführt, aber stürzt der Fehler, den ich bekommen ist

Unbehandelte Ausnahme bei 0x770215ee in doppelt verkettete list.exe: 0xC0000005: Zugriffsverletzung Schreibort 0x00000004.

Online-Debugger führt http://onlinegdb.com/Bkta6O6ig

Der Online-Debugger gibt drei Fehler, die ich in dem unten stehenden Code erwähnt habe mit Kommentaren

Meine Vermutung ist, dass es etwas falsch in der Add-Funktion der Klassenliste ist

Klasse Node

#include <iostream> 

using namespace std; 

class node 
{ 
private: 

    int data; 
    node *prev_pointer; 
    node *next_pointer; 

public: 

    int get_data() 
    { 
     return data; 
    } 

    void set_data(int data) 
    { 
     this->data = data; 
    } 



    node* get_prev_ptr() 
    { 
     return prev_pointer; 
    } 

    void set_next_ptr(node *Node) 
    { 
     next_pointer = Node; 
    } 

    node* get_next_ptr() 
    { 
     return next_pointer; 
    } 


    void set_prev_ptr(node *hi) 
    { 
     prev_pointer = hi; //First error 
    } 
}; 

Klassenliste

class List 
{ 
private: 

    int size; 
    node * cursor; 
    node * lastnode; 
    node * headnode; 

public: 

    List(); 
    void add(int data); 
    bool next(); 
    void previous(); 
    void start(); 
    void traverse(); 
    int get_data(); 
// ~List(); 
}; 

List :: List() 
{ 
    headnode = new node(); 
    cursor = NULL; 
    lastnode = NULL; 
    size = 0; 
} 

void List:: add(int data) 
{ 
    node *newnode = new node(); 
    newnode->set_data(data); 

     if (cursor != NULL) 
     { 
      newnode->set_next_ptr(cursor->get_next_ptr()); 
      newnode->set_prev_ptr(cursor); 
      (newnode->get_next_ptr())->set_prev_ptr(newnode); //2nd error 
      cursor->set_next_ptr(newnode); 
      lastnode = cursor; 
      cursor = cursor->get_next_ptr(); 
     } 
     else 
     { 
      newnode->set_next_ptr(NULL); 
      newnode->set_prev_ptr(headnode); 
      headnode->set_next_ptr(newnode); 
      cursor = newnode; 
      lastnode = headnode; 
     } 

    size++; 
} 

bool List :: next() 
{ 
    if (cursor != NULL) 
    { 
     return false; 
    } 
    else 
    { 
     lastnode = cursor; 
     cursor = cursor->get_next_ptr(); 
    } 

    if(cursor == NULL || size == 0) 
     return false; 
    else 
     return true; 
} 

void List :: traverse() 
{ 
    node *temp = cursor; 
    start(); 

    for (int i = 0 ; next() ; i++) 
    { 
     cout<<"element " << i << " " << cursor->get_data() <<endl; 
    } 
} 

void List :: start() 
{ 
    lastnode = headnode; 
    cursor = headnode; 
} 

int List :: get_data() 
{ 
    return cursor->get_data(); 
} 

Haupt

int main() 
{ 
    List list; 
    list.add(10); 
    list.add(11);   //3rd error 
    list.add(12); 
    //list.add(13); 
    //list.add(14); 
    //list.add(15); 

    list.traverse(); 

    return 0; 
} 
+1

Der Debugger wird Ihnen nur helfen, Probleme zu finden. Es wird keine Probleme für Sie finden. 'add' überprüft nicht, dass' newnode' einen Nicht-NULL-Zeiger erhalten hat, bevor er versucht hat, es zu verwenden. Es überprüft, dass 'cursor' nicht NULL ist, aber nicht, dass 'cursor's next nicht NULL ist. – user4581301

Antwort

3

Predendum: Lesen der debuger Ausgabe:

Program received signal SIGSEGV, Segmentation fault.           
0x0000000000400d20 in node::set_prev_ptr (this=0x0, hi=0x614c60) at main.cpp:46    
46      prev_pointer = hi; 

Hinweis this=0x0. Alle Klassenmethoden haben einen This-Zeiger, damit sie wissen, auf welche von vielen möglichen Instanzen sie zugreifen können. Hier zeigt this auf NULL. Das Programm kann kein gültiges prev_pointer von einem NULL-Objekt abrufen. Dies sagt Ihnen, dass Sie, um die wahre Ursache des Problems zu finden, herausfinden müssen, warum this ungültig ist.

Hier kommt der Callstack ins Spiel. Sie bewegen sich zurück zum Stapel, um herauszufinden, wo this zerstört wurde. Wir können sehen, dass set_prev_ptr uis aufgerufen wird auf die Ausgabe von get_next_ptr und get_next_ptr gibt next_pointer zurück. Der erste Ort zum Ausprobieren ist next_pointer. Setzen Sie newnode->next_pointer in "Display Expressions" zeigt next_pointer ist NULL.

Also warum ist next_pointer NULL? Bis ein paar Zeilen Code, den wir

newnode->set_next_ptr(cursor->get_next_ptr()) 

finden, so betrachten wir cursor->next_pointer und finden es NULL ist. Und jetzt kommen wir in den ursprünglichen Beitrag und zeichnen die verkettete Liste, weil es viel schneller ist, als den Debugger immer wieder auszuführen und erneut auszuführen.

Der beste Weg, um eine verknüpfte Liste zu debuggen, ist mit Bleistift und Papier: Zeichnen Sie es.Sie werden sehen, dass nach 10 hinzufügen, die Liste wie

11 sieht
head <-> 10 -> NULL 
cursor -> 10 -> NULL 
lastnode -> 10 -> NULL 

Zugabe wie leider

head <-> 10 <-> 11 -> NULL 
cursor -> 11 -> NULL 
lastnode -> 10 -> 11 -> NULL 

aussehen sollte es fehlschlägt, weil

(newnode->get_next_ptr())->set_prev_ptr(newnode); 

Versuche

11 -> NULL -> 11; 

Also ein

if (newnode->get_next_ptr() != NULL) 

ist erforderlich, um es zu schützen.

Darüber hinaus überdenken

lastnode = cursor; 

wie seit cursor ‚s nächsten Punkte auf newnode deutlich cursor nicht der letzte Knoten ist. Abhängig davon, wo cursor Punkte sind, kann auch newnode nicht der letzte Knoten sein.

Vorschläge:

diese aufgerissenen nächsten und zurück Accessoren Providing Ruinen node ‚s Verkapselung, weil jemand die Accessoren verwenden können, um node alles, was sie tun wollen. Sie können auch die Membervariablen public deklarieren und Zeit sparen.

Das sieht wie ein gutes Beispiel für List einen Knoten friend von node oder für sein, alle public Zugang zu sein (oder ein struct) und eingekapselt List vor neugierigen Augen. So oder so, verlieren Sie die Accessoren.

Verwandte Themen