После долгих царапин на голове, думаю, я заметил проблему. Код:
struct Block {
union {
void* address;
Block* next;
};
size_t size;
};
void* FragmentedMemoryManager::allocate(size_t size) {
if(allocationCount == maxAllocations) return nullptr;
Block** prev = &head;
Block* curr = head;
for(;
curr != nullptr;
prev = &curr,
curr = curr->next
)
{
if(curr->size < size) {
continue;
}
Block allocBlock = Block{
address: curr,
size: size
};
allocations[allocationCount++] = allocBlock;
size_t newSize = curr->size - size;
//pretty sure this will wrap if it goes 'negative'
assert(newSize < curr->size);
//curr was completely allocated
if(newSize == 0) {
*prev = curr->next;
} else {
void* newAddress = toPtr(toUPtr(curr) + size);
Block* newBlock = reinterpret_cast<Block*>(newAddress);
newBlock->next = curr->next;
newBlock->size = newSize;
if(*prev == head) {
*prev = newBlock;
} else {
//I know that this fails because prev is a double ref,
//updating curr in the loop unintentionally updates prev
//see line 36
(*prev)->next = newBlock;
}
}
std::sort(
allocations, allocations + allocationCount,
[](Block a, Block b)
{
return a.address < b.address;
});
memset(allocBlock.address, 0, size);
return allocBlock.address;
}
return nullptr;
}
Я убежден, что идея правильна в том, что мне нужно сделать (* prev) -> next = newBlock, я не знаю, как сохранить предполагаемую ссылку на prev, пока также обновление curr. Как мне это сделать?
Отступ вышел шатким. Поскольку здесь происходит нечто большее, чем просто добавление в список. Существует возможность предварительного перепрыгивания через курсор, по сути, «удаления» курсора. Я пишу узлы прямо в нераспределенные области памяти.