Double pointer memory pool
unknown
c_cpp
9 months ago
6.5 kB
59
Indexable
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
class MemoryPool {
public:
MemoryPool(size_t size)
: poolSize(size), used(0)
{
pool = new char[size];
}
~MemoryPool() {
delete[] pool;
for (auto& block : blocks) {
delete block.handle;
}
}
char** allocate(size_t size) {
for (auto it = freeList.begin(); it != freeList.end(); ++it) {
if (it->size >= size) {
size_t offset = it->offset;
char* blockPtr = pool + offset;
if (it->size == size) {
freeList.erase(it);
}
else {
it->offset += size;
it->size -= size;
}
char** handle = new char*;
*handle = blockPtr;
Block info;
info.handle = handle;
info.size = size;
info.offset = offset;
blocks.push_back(info);
return handle;
}
}
if (used + size > poolSize) {
std::cerr << "Not enough memory in the pool" << std::endl;
return nullptr;
}
size_t offset = used;
char* blockPtr = pool + offset;
used += size;
char** handle = new char*;
*handle = blockPtr;
Block info;
info.handle = handle;
info.size = size;
info.offset = offset;
blocks.push_back(info);
return handle;
}
void free(char** handle) {
auto it = std::find_if(blocks.begin(), blocks.end(),
[handle](const Block& block) { return block.handle == handle; });
if (it == blocks.end()) {
std::cerr << "Block not found" << std::endl;
return;
}
size_t offset = it->offset;
size_t size = it->size;
blocks.erase(it);
delete handle;
freeList.push_back({ offset, size });
mergeFreeList();
}
void defragment() {
std::sort(blocks.begin(), blocks.end(), [](const Block& a, const Block& b) {
return a.offset < b.offset;
});
size_t newOffset = 0;
for (auto& block : blocks) {
if (block.offset != newOffset) {
memmove(pool + newOffset, pool + block.offset, block.size);
block.offset = newOffset;
*block.handle = pool + newOffset;
}
newOffset += block.size;
}
used = newOffset;
freeList.clear();
if (used < poolSize) {
freeList.push_back({ used, poolSize - used });
}
}
void printBlocks() {
std::cout << "MemoryPool blocks:" << std::endl;
for (size_t i = 0; i < blocks.size(); i++) {
std::cout << "Block " << i << ": "
<< static_cast<void*>(*blocks[i].handle)
<< ", Size: " << blocks[i].size
<< ", Offset: " << blocks[i].offset
<< std::endl;
}
}
// Debug: Print the entire pool's contents.
void printPool() {
std::cout << "MemoryPool contains:" << std::endl;
for (size_t i = 0; i < poolSize; i++) {
std::cout << pool[i];
}
std::cout << std::endl;
}
private:
// Structure for allocated blocks – now with offset.
struct Block {
char** handle;
size_t size;
size_t offset;
};
// Structure for free blocks in the free list.
struct FreeBlock {
size_t offset;
size_t size;
};
char* pool; // The entire memory pool
size_t poolSize; // Total size of the pool
size_t used; // How much memory is used
std::vector<Block> blocks; // List of allocated blocks
std::vector<FreeBlock> freeList; // Free list with free areas
// Merges adjacent free blocks to reduce fragmentation.
void mergeFreeList() {
std::sort(freeList.begin(), freeList.end(), [](const FreeBlock& a, const FreeBlock& b) {
return a.offset < b.offset;
});
std::vector<FreeBlock> merged;
for (const auto& block : freeList) {
if (!merged.empty() && merged.back().offset + merged.back().size == block.offset) {
merged.back().size += block.size;
}
else {
merged.push_back(block);
}
}
freeList = std::move(merged);
}
};
int main() {
MemoryPool pool(100);
// Allocate some blocks.
char** ptr1 = pool.allocate(10); // Block 0
char** ptr2 = pool.allocate(20); // Block 1
char** ptr3 = pool.allocate(15); // Block 2
char** ptr4 = pool.allocate(5); // Block 3
strcpy(*ptr1, "[1111111]");
strcpy(*ptr2, "[22222222222222222]");
strcpy(*ptr3, "[333333333333]");
strcpy(*ptr4, "[44]");
std::cout << "Before free:" << std::endl;
pool.printBlocks();
pool.printPool();
pool.free(ptr2);
std::cout << "\nAfter freeing ptr2:" << std::endl;
pool.printBlocks();
pool.printPool();
// Allocate a new block that should take place in a hole from the free list.
char** ptr5 = pool.allocate(16);
strcpy(*ptr5, "[5555555555555]");
std::cout << "\nAfter allocating new block:" << std::endl;
pool.printBlocks();
pool.printPool();
// Perform defragmentation.
pool.defragment();
std::cout << "\nAfter defragementation:" << std::endl;
pool.printBlocks();
pool.printPool();
// Check the contents via the original pointers:
std::cout << "\nExisting pointers:" << std::endl;
std::cout << "ptr1: " << *ptr1 << std::endl;
std::cout << "ptr3: " << *ptr3 << std::endl;
std::cout << "ptr4: " << *ptr4 << std::endl;
std::cout << "ptr5: " << *ptr5 << std::endl;
// Buffer overflow test ptr1
strcpy(*ptr1, "[11111111111]");
std::cout << "\nAfter buffer overflow test ptr1:" << std::endl;
pool.printPool();
std::cout << "ptr1: " << *ptr1 << std::endl;
std::cout << "ptr3: " << *ptr3 << std::endl;
std::cout << "ptr4: " << *ptr4 << std::endl;
std::cout << "ptr5: " << *ptr5 << std::endl;
return 0;
}
Editor is loading...
Leave a Comment