Warum speichern interne Lua-Zeichenketten so wie sie es tun?

8

Ich wollte eine einfache String-Tabelle, die eine Reihe von Konstanten speichert und ich dachte "Hey! Lua macht das, lass mich einige der Funktionen verwenden!"

Dies ist hauptsächlich in den lstring.h / lstring.c Dateien (ich benutze 5.2)

Ich werde den Code zeigen, über den ich zuerst neugierig bin. Es ist von lobject.h

%Vor%

Wie Sie sehen, werden die Daten außerhalb der Struktur gespeichert. Um den Byte-Stream zu erhalten, nehmen Sie die Größe von TString, fügen Sie 1 hinzu, und Sie haben den char * -Zeiger erhalten.

Ist das nicht schlecht? Es wurde in meinen C-Klassen in m gebohrt, um klar definierte Strukturen zu erhalten. Ich weiß, dass ich hier ein Nest rühren könnte, aber verlieren Sie wirklich so viel Geschwindigkeit / Platz, um eine Struktur als Header für Daten zu definieren, anstatt einen Zeigerwert für diese Daten zu definieren?

    
Paul Bruner 23.01.2012, 23:13
quelle

3 Antworten

5

Die Idee ist wahrscheinlich, dass Sie den Header und die Daten in einem großen Datenblock statt zwei zuordnen:

%Vor%

Zusätzlich zu nur einem Aufruf von malloc / free reduzieren Sie auch die Speicherfragmentierung und erhöhen die Speicherlokalisierung.

Aber Ihre Frage zu beantworten, ja, diese Art von Hacks sind in der Regel eine schlechte Praxis und sollten mit äußerster Sorgfalt durchgeführt werden. Und wenn Sie dies tun, werden Sie sie wahrscheinlich unter einer Ebene von Makros / Inline-Funktionen verstecken wollen.

    
rodrigo 23.01.2012, 23:21
quelle
2

Wie Rodrigo sagt, besteht die Idee darin, die Header- und String-Daten als ein einziges Stück Speicher zuzuordnen. Es ist erwähnenswert, dass Sie auch den Nicht-Standard-Hack sehen

%Vor%

aber C99 hat flexible Array-Mitglieder hinzugefügt, so dass dies in einer standardkonformen Weise wie

geschehen kann %Vor%

Wenn Lua's String auf diese Weise gemacht würde, wäre es etwas wie

%Vor%     
Geoff Reedy 23.01.2012 23:57
quelle
1

Sie bezieht sich auf die Komplikationen, die sich aus der eingeschränkteren C-Sprache ergeben. In C ++ würden Sie einfach eine Basisklasse namens GCObject definieren, die die Garbage Collection-Variablen enthält, dann wäre TString eine Unterklasse und mit einem virtuellen Destruktor wären sowohl die TString als auch die begleitenden const char * Blöcke richtig befreit.

Wenn es darum geht, die gleiche Art von Funktionalität in C zu schreiben, ist es etwas schwieriger, da Klassen und virtuelle Vererbung nicht existieren.

Was Lua tut, ist die Implementierung der Garbage Collection, indem der Header eingefügt wird, der für die Verwaltung des Speicherbereinigungsstatus des darauf folgenden Speicherbereichs erforderlich ist. Denken Sie daran, dass free(void *) nichts anderes als die Adresse des Speicherblocks wissen muss.

%Vor%

Lua führt eine verknüpfte Liste dieser "sammelbaren" Speicherblöcke, in diesem Fall ein Array von Zeichen, so dass es dann den Speicher effizient freigeben kann, ohne den Typ des Objekts zu kennen, auf das es zeigt.

Wenn Ihr TString auf einen anderen Speicherblock zeigt, in dem sich das Zeichenarray befand, muss der Garbage Collector den Typ des Objekts bestimmen und dann in seine Struktur eintauchen, um auch den Zeichenfolgenpuffer freizugeben.

Der Pseudocode für diese Art von Garbage Collection wäre etwa so:

%Vor%     
Nick Bedford 21.12.2014 05:22
quelle

Tags und Links