Sie entwerfen eine neue esoterische Programmiersprache und eine Funktion, die Sie hinzufügen möchten, ist ein dynamischer Speicherzuweiser. Ihre Sprache gibt einen speziellen dedizierten virtuellen Adressraum für den Programmraum des Benutzers an. Dies ist getrennt von dem Adressraum, der vom Speicherzuweiser für einen internen Status verwendet wird.
Um die Kosten für die Verteilung Ihrer Implementierung zu senken, muss der Code so klein wie möglich sein.
Schnittstelle
Sie müssen drei Funktionen bereitstellen: Initialisierung, Zuweisung und Freigabe.
Initialisierung
Diese Funktion verwendet einen einzelnen positiven ganzzahligen Parameter N. Dies bedeutet, dass das Programm eines Benutzers NBytes in seinem Adressraum hat, aus denen N-1Bytes zum Zuweisen von Speicher vorhanden sind . Die Adresse 0ist für "null" reserviert.
Es ist garantiert, dass diese Funktion genau einmal aufgerufen wird, bevor Allokations- / Freigabeaufrufe ausgeführt werden.
Beachten Sie, dass diese Funktion keinen physischen Speicher für den virtuellen Adressraum des Benutzerprogramms zuweisen muss. Sie erstellen im Grunde das "Look and Feel" eines hohlen Speicherzuweisers.
Zuweisen
Die Zuweisungsfunktion muss eine Anforderung der Anzahl der zuzuweisenden Speicherbytes entgegennehmen. Die Eingabe ist garantiert positiv.
Ihre Funktion muss eine ganzzahlige Adresse an den Anfang des zugewiesenen Blocks zurückgeben oder 0angeben, dass kein zusammenhängender Block der angeforderten Größe verfügbar ist. Wenn ein zusammenhängender Block der verfügbaren Größe irgendwo im Adressraum verfügbar ist, müssen Sie ihn zuweisen!
Sie müssen sicherstellen, dass sich keine zwei zugewiesenen Blöcke überlappen.
Freigeben
Die Freigabefunktion muss eine Adresse für den Start eines zugewiesenen Blocks annehmen und kann optional auch die Größe des angegebenen Blocks annehmen.
Der freigegebene Speicher steht wieder zur Zuweisung zur Verfügung. Es wird angenommen, dass die Eingabeadresse eine gültige Adresse ist.
Beispiel für eine Python-Implementierung
Beachten Sie, dass Sie eine beliebige Methode wählen können, um den internen Status zu verfolgen. In diesem Beispiel verfolgt die Klasseninstanz dies.
class myallocator:
def __init__(self, N):
# address 0 is special, it's always reserved for null
# address N is technically outside the address space, so use that as a
# marker
self.addrs = [0, N]
self.sizes = [1, 0]
def allocate(self, size):
for i,a1,s1,a2 in zip(range(len(self.addrs)),
self.addrs[:-1], self.sizes[:-1],
self.addrs[1:]):
if(a2 - (a1+s1) >= size):
# enough available space, take it
self.addrs.insert(i+1, a1+s1)
self.sizes.insert(i+1, size)
return a1+s1
# no contiguous spaces large enough to take our block
return 0
def deallocate(self, addr, size=0):
# your implementation has the option of taking in a size parameter
# in this implementation it's not used
i = self.addrs.index(addr)
del self.addrs[i]
del self.sizes[i]
Wertung
Das ist Code Golf; Der kürzeste Code in Bytes gewinnt. Sie müssen sich keine Sorgen machen, dass Ihnen der Speicher für einen von Ihrem Allokator benötigten internen Status ausgeht.
Es gelten Standardschlupflöcher.
Bestenliste
To help reduce the cost of distributing your implementation the size of the code must be as small as possibleoder könnte es so effizient wie möglich sein (klein und effizient sind nicht dasselbe)? : D