Skip to content

Instantly share code, notes, and snippets.

@diffstorm
Created August 13, 2023 13:57
Show Gist options
  • Save diffstorm/dbed8028ee4f8e80984cf42d78ddf33a to your computer and use it in GitHub Desktop.
Save diffstorm/dbed8028ee4f8e80984cf42d78ddf33a to your computer and use it in GitHub Desktop.
Static memory allocator for embedded systems in C with auto fragmentation where malloc is unwanted
/*
Static memory allocator for embedded systems in C with auto fragmentation where malloc is unwanted
Author : Eray Ozturk | [email protected]
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
struct BlockHeader {
size_t size;
struct BlockHeader* next;
};
typedef struct {
char* buffer;
size_t bufferSize;
struct BlockHeader* head;
} StaticMemoryAllocator;
void initializeAllocator(StaticMemoryAllocator* allocator, char* buffer, size_t bufferSize) {
allocator->buffer = buffer;
allocator->bufferSize = bufferSize;
allocator->head = (struct BlockHeader*)buffer;
allocator->head->size = bufferSize - sizeof(struct BlockHeader);
allocator->head->next = NULL;
}
void* allocate(StaticMemoryAllocator* allocator, size_t size) {
if (size == 0 || size > allocator->bufferSize) {
return NULL; // Invalid size
}
struct BlockHeader* prev = NULL;
struct BlockHeader* curr = allocator->head;
while (curr) {
if (curr->size >= size) {
// Allocate from the current block
if (curr->size > size + sizeof(struct BlockHeader)) {
// Split the block
struct BlockHeader* newBlock = (struct BlockHeader*)((char*)curr + sizeof(struct BlockHeader) + size);
newBlock->size = curr->size - size - sizeof(struct BlockHeader);
newBlock->next = curr->next;
curr->size = size;
curr->next = newBlock;
}
// Update the free list
if (prev) {
prev->next = curr->next;
} else {
allocator->head = curr->next;
}
return (char*)curr + sizeof(struct BlockHeader);
}
prev = curr;
curr = curr->next;
}
return NULL; // Not enough memory
}
void deallocate(StaticMemoryAllocator* allocator, void* ptr) {
if (ptr >= allocator->buffer && ptr < allocator->buffer + allocator->bufferSize) {
struct BlockHeader* block = (struct BlockHeader*)((char*)ptr - sizeof(struct BlockHeader));
block->next = allocator->head;
allocator->head = block;
}
}
void cleanupAllocator(StaticMemoryAllocator* allocator) {
struct BlockHeader* curr = allocator->head;
while (curr) {
curr->size = 0;
curr->next = NULL;
curr = curr->next;
}
}
int main() {
size_t bufferSize = 1024;
char memoryBuffer[1024];
StaticMemoryAllocator memoryAllocator;
initializeAllocator(&memoryAllocator, memoryBuffer, bufferSize);
// Allocate an int
int* intPtr = (int*)allocate(&memoryAllocator, sizeof(int));
if (intPtr) {
*intPtr = 42;
printf("Allocated int: %d\n", *intPtr);
} else {
printf("Memory allocation failed\n");
}
// Allocate a double block
double* doublePtr = (double*)allocate(&memoryAllocator, sizeof(double));
if (doublePtr) {
*doublePtr = 3.14;
printf("Allocated double: %.2lf\n", *doublePtr);
} else {
printf("Memory allocation failed\n");
}
// Deallocate the int block
if (intPtr) {
deallocate(&memoryAllocator, intPtr);
intPtr = NULL;
printf("Deallocated int\n");
}
// Allocate a larger block
char* charPtr = (char*)allocate(&memoryAllocator, 256);
if (charPtr) {
printf("Allocated 256 bytes\n");
} else {
printf("Memory allocation failed\n");
}
// Clean up the allocator (release all memory)
cleanupAllocator(&memoryAllocator);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment