2017-12-20 6 views
1

HintergrundSingly Linked-List (Wie man richtig entfernen/eine Einheit befreien?)

Ich habe den folgenden Code

VOID FD_Remove(FDescs List, PVOID FileDesc) { 
    while (List) { 
     if (List->Sock == FileDesc) { 
      List->Next = (FDescs) LocalAlloc(sizeof(Network::FDesc)); 
      if (List->Next != ERROR) { 
       FDescs Element = List->Next; 

       List->Sock = List->Next->Sock; 
       List->Host = List->Next->Host; 
       List->Path = List->Next->Path; 

       List->Next = Element->Next; 
       LocalFree(Element); 
      } 
     } List = List->Next; 
    } 
} 

Hinweise

Grundsätzlich, wenn ich schaffe ein neuer Eintrag in der verknüpften Liste. Ich werde einen neuen Speicherblock der gegebenen Strukturgröße zuweisen und ihn an das Ende der Liste setzen, um einen Block auf die gleiche Weise wie in dieser _Remove Funktion zu finden.

Allerdings, wenn ich versuche, eine Entität zu entfernen. Ich lösche die Entität von der Liste, wie oben gezeigt, und setze die aktuelle Entität auf den nächsten Eintrag in der Liste. Das Problem ist, dass der LocalFree-Aufruf den zugewiesenen Speicher nicht tatsächlich auf einen nicht zugeordneten Speicherblock zurücksetzt. Wenn ich auf die verknüpfte Liste schaue, sind in der aktuellen Entity einfach alle Einträge auf NULL (0) gesetzt.

Angenommen, die FileDesc, die ich an FD_Remove übergebe, ist der letzte Eintrag der Liste.

FD_Remove(FDescList, 0x00000005);

So können wir davon ausgehen, dass der Speicher, der die 0x00000005 Einheit hat nun befreit.

Jetzt nenne ich FD_Add(FDescList, FileDesc, 'whatever');

würde ich nur annehmen, dass diese Werte in der zuvor befreit Einheit in der Linked-Liste erscheinen würden.

Problem

Das Problem ist, dass Einheit NULL anstelle von freigegebenen Speicher gesetzt ist, und die Funktion fügt die FileDesc und ‚unabhängig‘ Daten an die Einheit nach dem NULL Speicherblock anstelle des im Inneren davon.

Frage

Was bin ich in meiner FD_Remove Funktion falsch zu machen, dass dies verursacht, und wie kann ich meine Funktion verbessern, dieses Problem zu beheben?

Antwort

2

Das Entfernen eines Elements aus einer verknüpften Liste beinhaltet einfach das Aktualisieren der umgebenden Elementzeiger auf das Element, das entfernt wird, und dann das Freigeben des Elements. Sie müssen nichts zuweisen oder kopieren.

Versuchen Sie stattdessen:

VOID FD_Remove(FDescs List, PVOID FileDesc) { 
    FDescs Previous = NULL; 
    while (List) { 
     if (List->FDesc == FileDesc) { 
      if (Previous) 
       Previous->Next = List->Next; 
      LocalFree(List); 
      return; 
     } 
     Previous = List; 
     List = List->Next; 
    } 
} 

FD_Remove(FDescList, (PVOID)0x00000005); 

Aber wehe, wenn das Element entfernt wird, die head der verknüpften Liste ist. Wenn ja, müssen Sie auch diesen Zeiger aktualisieren, was die obige Funktion nicht direkt tun kann. Sie müssten stattdessen etwas mehr tun:

VOID FD_Remove(FDescs *List, PVOID FileDesc) { 
    if (!List) return; 
    FDescs Element = *List, Previous = NULL; 
    while (Element) { 
     if (Element->FDesc == FileDesc) { 
      if (*List == Element) 
       *List = Element->Next; 
      if (Previous) 
       Previous->Next = Element->Next; 
      LocalFree(Element); 
      return; 
     } 
     Previous = Element; 
     Element = Element->Next; 
    } 
} 

FD_Remove(&FDescList, (PVOID)0x00000005);