Bei der Implementierung einer verketteten Liste in C wer ist verantwortlich für die Freigabe des Wertes?

8

Ich implementiere eine verkettete Liste in C und ich laufe auf das Problem ein, bei dem C kein spezifisches Schema für die Speicherverwaltung implementiert, außer Ihnen nur die Möglichkeit zu geben, Speicher zuzuteilen und freizugeben, indem Sie einen Zeiger übergeben. Es gibt kein Konzept, ob der Wert später im Programm benötigt wird.

Die typische Implementierung, die ich online für eine verknüpfte Liste finde, hebt im Grunde den gelöschten Knoten auf, löscht aber nicht den Wert des Knotens.

Wessen Verantwortung sollte es sein, den Speicher freizugeben, den der Wert einnimmt, wenn er aus der Liste gelöscht wird? Die verknüpfte Liste oder der normale Ablauf des Programms?

Beispiel:

%Vor%

In diesem Fall würde Text nicht freigegeben werden, da list_remove_last nur den Speicher freigibt, den der neue Knoten belegt. Was wäre der richtige Weg, um die vom Text belegte Speicherkapazität freizugeben?

    
Abel Duarte 09.12.2015, 16:30
quelle

4 Antworten

4

das ist eine sehr häufige Art der Containerimplementierung in C. Im Grunde genommen ordnen Sie den Inhalt der Liste dynamisch zu und übergeben den Zeiger an den Container. Nun ist der Container für die Freigabe zuständig.

Sie können auch einen Funktionszeiger an list_create() übergeben, damit er list_remove_last() richtig erkennt. Dies ist besonders nützlich für die Verwendung eines generischen Containers, der nicht weiß, welche Art von Elementen er enthalten soll (es wird nur funktionieren) halte void * Zeiger). Denken Sie an den Fall, wo die Daten selbst eine Struktur sind, die andere Zeiger enthält. In diesem Fall kann list_remove () in seinem Datenfeld kein einfaches free () ausführen, stattdessen sollte der Funktionszeiger verwendet werden, der übergeben wurde, um die Daten freizugeben.

Ihr Ansatz hat ein kleines Problem:

Wenn Sie list * als Rückgabetyp von list_create () haben, müssen Sie eine freie Liste in Ihrer Hauptfunktion erstellen. alternativ können Sie list_create () eine Liste zurückgeben, im Gegensatz zu einer Liste *, dies ist eine logische Wahl, da eine Liste ihre Informationsmenge dynamisch zugewiesen hat und trotzdem über einen Zeiger zugänglich ist.

Im zweiten Fall benötigen Sie eine Funktion list_destroy (Liste), die jedes Element Ihrer Liste zerstören würde.

    
ForeverStudent 09.12.2015, 16:41
quelle
3

Meine Richtlinie lautet: Derjenige, der Speicher zuweist, ist auch für die Aufhebung der Zuweisung zuständig.

Wenn Sie eine verkettete Liste implementieren, die den Speicher für die Werte zuweist, sollte die Implementierung auch dafür sorgen, diesen Speicher freizugeben, wenn die Einträge aus der Liste entfernt werden. Bei Strings könnte dies durch Kopieren der Strings in einen neu zugewiesenen Puffer geeigneter Größe erfolgen.

Wenn Ihre Implementierung einer verknüpften Liste nur einfache Werte (z. B. Zeiger) speichert, ohne zusätzlichen Speicher für die Werte zuzuweisen, sollte sie auch nicht freigegebenen Speicher freigeben, da sie nicht weiß, was der Zuordner für diesen Speicher geplant hat in der Zukunft.

    
René Vogt 09.12.2015 16:42
quelle
2

Der richtige Weg wäre, list_remove_node() eine Funktion zu haben, die nicht nur die Liste (Knoten) selbst freigibt, sondern auch den Wert, der für diesen spezifischen Knoten zugewiesen wurde. Außerdem sollten Sie nicht nach einem bestimmten Knoten nach Ihrem Text suchen müssen, da Sie einfach free(node->text) aufrufen können (was sogar in der aktuellen Funktion list_remove_last() möglich ist)

Die wichtigste C-Logik ist, dass Sie alles, was Sie selbst zugewiesen haben, freigeben (). Bestimmte Bibliotheken werden Speicher für ihre eigene Arbeit zuweisen, die Sie am häufigsten auch bereinigen sollten (wie Sie es waren, der danach gefragt hat).

    
prkist 09.12.2015 16:47
quelle
2
  

C implementiert kein spezifisches Schema für die Speicherverwaltung, außer Ihnen die Möglichkeit zu geben, Speicher zuzuweisen und freizugeben, indem Sie einen Zeiger übergeben

Ja, C verfügt nicht über eine automatische Speicherverwaltung, daher müssen Sie darauf achten, alle Speicherblöcke, die Sie instanziieren, aufzuheben.

  

Wessen Verantwortung sollte es sein, den Speicher freizugeben, den der Wert einnimmt, wenn er aus der Liste gelöscht wird? Die verknüpfte Liste oder der normale Ablauf des Programms?

Es liegt in Ihrer Verantwortung. Sie können es tun, wie Sie wollen. Sie können eine verknüpfte Liste für allgemeine Zwecke schreiben, bei der der Aufrufer für das Zuweisen und Freigeben von Speicherplatz für jeden Wert in der Liste verantwortlich sein muss, da die Listenverwaltungsfunktionen nicht wissen, wie viel Platz für jeden Wert erforderlich ist oder ob die Werte möglicherweise benötigt werden über die Lebensdauer des Knotens hinaus. Oder Sie können eine Listenimplementierung schreiben, die alle Aspekte des Knotens verwaltet, einschließlich Platz für den im Knoten gespeicherten Wert. In einigen Fällen enthält ein Listenknoten den Wert in der Knotendefinition wie

%Vor%

und zu anderen Zeiten hat der Knoten einen Zeiger auf einen anderen Block, der den tatsächlichen Wert hat:

%Vor%

Ein anderer Ansatz besteht darin, eine Struktur zu definieren, die nur den Teil enthält, der für die Listenoperation benötigt wird (d. h. den next -Zeiger), und dann Daten auf diese Struktur huckepack zu setzen:

%Vor%

Also, es gibt viele Möglichkeiten, es zu tun, und keiner von ihnen ist falsch. Sie sollten den Stil wählen, der für Ihre Bedürfnisse sinnvoll ist. Haben Sie große, komplexe Werte, die Sie nicht duplizieren möchten, die Sie in einer verknüpften Liste speichern möchten, die Sie aber auch nach dem Entfernen aus der Liste weiterhin verwenden möchten? Geh mit dem ersten Stil oben. Möchten Sie alles, was mit der verknüpften Liste zusammenhängt, an einem Ort verwalten? Dann geh mit dem zweiten Stil.

Der springende Punkt ist: C diktiert viel weniger als andere Sprachen, und das bedeutet, dass Sie sich mehr Gedanken um die Programmkorrektheit machen müssen, aber Sie haben auch die Freiheit, Dinge sehr direkt und in einem Stil Ihrer Wahl zu tun. Umarme das.

    
Caleb 09.12.2015 16:52
quelle