Double pointer memory pool
unknown
c_cpp
5 days ago
6.5 kB
41
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