2017-01-06 6 views
0

Ich erstelle derzeit eine Planetensimulation und habe ein Problem, wenn ich versuche, Planeten zu löschen, wenn sie miteinander kollidieren, siehe unten.C Doppelt verknüpfte Liste Lesezugriffsverletzung

Ich habe derzeit ein Problem mit dem Löschen von Elementen aus meiner Double Linked List, was zu einer Lesezugriffsverletzung führt, die besagt, dass eines der Elemente "0xFFFFFFFFFFFFFFFCB" war. Ich bin relativ neu in C, daher glaube ich, dass ich irgendwo etwas vermisse.

Bitte beachten Sie, dass der Fehler nicht auftritt, wenn die remove() - Methode ohne die destroy() -Methode verwendet wird. Sie tritt nur auf, wenn die Methode destroy() mit/remove() nur verwendet wird gelegentlich dabei.

Der Code ist unten angehängt:

struct planet *head; //Head of list 
struct planet *tail; //Tail of list 

struct planet { 
    //Data 
    float mass; 
    struct planet *next; 
    struct planet *prev; 
}; 

planet *removeTail() { 
    struct planet* p = tail; 
    if (tail) { 
     if (head == tail) { 
      head = tail = 0; 
     } 
     else { 
      tail = tail->prev; 
      p->prev = 0; 
      tail->next = 0; 
     } 
    } 
    return p; 
} 

planet *removeHead() { 
    struct planet* p = head; 
    if (head) { 
     if (head == tail) { 
      head = tail = 0; 
     } 
     else { 
      head = head->next; 
      p->next = 0; 
      head->prev = 0; 
     } 
    } 
    return p; 
} 

planet *remove(struct planet* p) {//Breaking the tree 
    if (p == head) { 
     removeHead(); 
    } 
    else if (p == tail) { 
     removeTail(); 
    } 
    else { 
     p->prev->next = p->next; 
     p->next->prev = p->prev; 
    } 
    return p; 
} 

planet *destroy(struct planet* p) { 
    if (p) { 
     if (p != head || p != tail || (!p->next && p->prev)) { 
      delete p; 
      printf("Deleted\n"); 
      return 0; 
     } 
     else { 
      printf("Not deleted\n"); 
      return 0; 
     } 
    } 
} 

for (struct planet *p1 = head; p1 != 0; p1 = p1->next) 
{ 
    for (struct planet *p3 = head; p3 != 0; p3 = p3->next) 
     { 
      //Collision logic 
      if(p1 != p3){ 
       if(p1->mass >= p3->mass){ 
        destroy(remove(p3)); //Does not cause an error 
        break; 
       }else{ 
        destroy(remove(p1)); //Causes the error. 
        break; 
        //Deleting p1 here means the for loop can't move on 
       } 
      } 
     } 
} 

Ich glaube, ich habe alle relevanten Code oben enthalten, wenn Sie weitere Informationen benötigen, lassen Sie es mich wissen. Mir ist auch nicht bewusst, was genau den Fehler auslöst, dass die Simulation manchmal mehrere Knoten ohne Probleme entfernen und löschen kann, in anderen Fällen kann sie nur einen entfernen.

Jeder Rat würde sehr geschätzt werden!

+0

Ich denke nicht, dass dies als opengl markiert werden sollte, da das Codebeispiel es nicht verwendet. – SurvivalMachine

+0

Es gibt tatsächlich drei Schleifen, ich habe fälschlicherweise nur zwei oben gezeigt, ich werde den Code jetzt korrigieren. Ich habe auch das OpenGL-Tag entfernt, meine Entschuldigung. – Alex

+0

Der zusätzliche Code wurde hinzugefügt. – Alex

Antwort

0

Nur so hat dies eine Antwort, das Problem war, dass die äußere for-Schleife innerhalb der p3-Schleife unterbrochen wurde. p1 muss einfach gelöscht werden, damit die Schleife nicht zerstört wird.

1

Der Löschcode könnte eine einzige Funktion sein:

planet *remove(struct planet* p) 
    if (p->prev == NULL) { 
     head = p->next; 
    } 
    else { 
     p->prev->next = p->next; 
    } 

    if (p->next == NULL) { 
     tail = p->prev; 
    } 
    else { 
     p->next->prev = p->prev; 
    } 
    return p; 
} 

Und vielleicht sollte es eine free(p) irgendwo sein.

+0

Es wäre sinnvoller, aber der Dozent für die Klasse möchte mehrere Methoden für die LinkedList sehen, einschließlich der Entfernung von Kopf und Schwanz. In Bezug auf die Verwendung von 'free (p)', ist nicht 'delete p;' in der 'destroy()' Methode, die das handhabt? – Alex

+0

@Alex Nicht in der Sprache C. Es gibt kein 'delete'. – WhozCraig

+0

Entschuldigung, Sie haben dies als C markiert. Die Funktion, die ich geschrieben habe, funktioniert für jedes Element der doppelt verknüpften Liste, aber was passiert, wenn Sie weiter iterieren, ist schwerer zu sehen. Und wenn Sie den Speicher für "p" zurück zum System gegeben haben, dürfen Sie ihn nicht wieder dereferenzieren (wie in einer der Schleifensteuerungen). –

Verwandte Themen