Você está projetando uma nova linguagem de programação esotérica e um recurso que decidiu adicionar é um alocador de memória dinâmico. Seu idioma especifica um espaço de endereço virtual dedicado especial para o espaço do programa do usuário. Isso é separado do espaço de endereço usado pelo alocador de memória para qualquer estado interno.
Para ajudar a reduzir o custo de distribuição de sua implementação, o tamanho do código deve ser o menor possível.
Interface
Você deve fornecer três funções: inicialização, alocação e desalocação.
Inicialização
Esta função aceita um único parâmetro inteiro positivo N. Isso significa que o programa de um usuário possui Nbytes no espaço de endereço dos quais existem N-1bytes para alocar memória. O endereço 0está reservado para "nulo".
É garantido que esta função será chamada exatamente uma vez antes de qualquer chamada de alocação / desalocação.
Observe que essa função não precisa alocar memória física para o espaço de endereço virtual do programa do usuário; você está basicamente criando a "aparência e aparência" de um alocador de memória vazio.
distribuir
A função de alocação deve receber uma solicitação do número de bytes de memória a ser alocada. A entrada é garantida para ser positiva.
Sua função deve retornar um endereço inteiro para o início do bloco alocado ou 0para indicar que não há nenhum bloco contíguo do tamanho solicitado disponível. Se um bloco contíguo do tamanho disponível estiver disponível em qualquer lugar do espaço de endereço, você deverá alocar!
Você deve garantir que nenhum dos dois blocos alocados se sobreponha.
Desalocar
A função de desalocação deve assumir um endereço do início de um bloco alocado e, opcionalmente, também pode assumir o tamanho do bloco especificado.
A memória desalocada está disponível novamente para alocação. Supõe-se que o endereço de entrada seja um endereço válido.
Exemplo de implementação em Python
Observe que você pode escolher qualquer método para acompanhar o estado interno; neste exemplo, a instância da classe controla isso.
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]
Pontuação
Isso é código de golfe; o menor código em bytes vence. Você não precisa se preocupar com a falta de memória para qualquer estado interno exigido pelo seu alocador.
Aplicam-se orifícios de loop padrão.
Entre os melhores
To help reduce the cost of distributing your implementation the size of the code must be as small as possibleou poderia ser eficiente (pequeno e eficiente não são os mesmos) possível? : D