I am trying to implement buddy allocator in C for FreeRTOS.
I made a function buddy_free for memory management.
I am using struct _buddy_block and function for allocation and memory management, but things don't go well and I need your help.
Here's my sources and problems below:
typedef struct _buddy_block {
struct _buddy_block *next;
size_t size;
bool is_free;
} buddy_block_t;
typedef struct {
buddy_block_t *freelist;
size_t total_size;
size_t min_block_size;
} buddy_allocator_t;
Allocation:
void *buddy_alloc(buddy_allocator_t *allocator, size_t size) {
// Find the first free block that is large enough to satisfy the request
buddy_block_t *block = allocator->freelist;
while (block != NULL && (block->size < size || !block->is_free)) {
block = block->next;
}
// If no suitable block was found, return NULL
if (block == NULL) {
return NULL;
}
// Split the block into two blocks if the block is larger than needed
if (block->size > size) {
// Create a new block for the remainder
buddy_block_t *remainder = (buddy_block_t *) ((uint8_t *) block + size);
remainder->size = block->size - size;
remainder->is_free = true;
remainder->next = block->next;
// Update the current block
block->size = size;
block->next = remainder;
}
// Mark the block as allocated and return a pointer to the memory
block->is_free = false;
return (void *) (block + 1);
}
void buddy_free(buddy_allocator_t *allocator, void *ptr) {
// Get a pointer to the block header
buddy_block_t *block = (buddy_block_t *) ptr - 1;
if (block->is_free) {
return;
}
// Mark the block as free
block->is_free = true;
// Try to merge the block with its buddy (if it has one and the buddy is free)
size_t block_size = block->size;
buddy_block_t *buddy = (buddy_block_t *) ((uint8_t *) block + block_size);
// Check if the buddy block is within the memory region managed by the allocator
if (block < allocator->freelist ||
block > (buddy_block_t *) ((uint8_t *) allocator->freelist + allocator->total_size) ||
buddy < allocator->freelist ||
buddy > (buddy_block_t *) ((uint8_t *) allocator->freelist + allocator->total_size)) {
// One of the blocks is outside of the memory region managed by the allocator, so they cannot be merged
return;
}
// Check if the buddy block is free and has the same size as the current block
if (buddy->is_free && buddy->size == block_size) {
// The buddy is free and has the same size as the current block, so they can be merged
if (buddy < block) {
// The buddy comes before the current block in memory, so it should be the new block
buddy->size *= 2;
buddy->next = block->next;
block = buddy;
} else {
// The current block comes before the buddy in memory, so it should be the new block
block->size *= 2;
block->next = buddy->next;
}
}
// Insert the merged block back into the free list
buddy_block_t *prev = NULL;
buddy_block_t *curr = allocator->freelist;
while (curr != NULL && curr < block) {
prev = curr;
curr = curr->next;
}
block->next = curr;
if (prev == NULL) {
allocator->freelist = block;
} else {
prev->next = block;
}
}
First problem is that in the line:
while (block != NULL && (block->size < size || !block->is_free))
I get Segmentation fault with test_buddy_alloc_insufficient_memory test:
// Test the behavior of the buddy_alloc function when it is unable to fulfill an allocation request due to insufficient free memory
void test_buddy_alloc_insufficient_memory() {
// Allocate all of the available memory
buddy_allocator_t allocator;
void *ptr = buddy_alloc(&allocator, allocator.total_size);
assert(ptr != NULL);
// Attempt to allocate more memory
ptr = buddy_alloc(&allocator, 1);
assert(ptr == NULL);
}
// Test the behavior of the buddy_alloc function when it is called with a size of 0
void test_buddy_alloc_size_zero() {
buddy_allocator_t allocator;
// Attempt to allocate a block of size 0
void *ptr = buddy_alloc(&allocator, 0);
assert(ptr == NULL);
}
Can someone help me to fix or improve my code?
You have UB (undefined behavior).
In your test_* functions, you have:
buddy_allocator_t allocator;
This is on the stack and is uninitialized.
You need:
buddy_allocator_t allocator = { 0 };
With -Wall, the compiler flags:
orig.c: In function ‘test_buddy_alloc_insufficient_memory’:
orig.c:114:14: warning: ‘allocator.total_size’ is used uninitialized in this function [-Wuninitialized]
void *ptr = buddy_alloc(&allocator, allocator.total_size);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Also, in buddy_alloc, the first thing it does is:
buddy_block_t *block = allocator->freelist;
while (block != NULL && (block->size < size || !block->is_free))
The block != NULL is insufficient. It does not guard against dereferencing a non-null but random/invalid pointer value.
UPDATE:
From the discussion and further review, I didn't see any code to set up the allocator struct with a valid block. So, the allocator started without any memory.
Normally, we'd call brk/sbrk to get more memory from the system, but, for testing, we can use a static/persistent fixed array.
Here is the restructured code:
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>
typedef struct _buddy_block {
struct _buddy_block *next;
size_t size;
bool is_free;
} buddy_block_t;
typedef struct {
buddy_block_t *freelist;
size_t total_size;
size_t min_block_size;
} buddy_allocator_t;
void *
buddy_alloc(buddy_allocator_t * allocator, size_t size)
{
// Find the first free block that is large enough to satisfy the request
buddy_block_t *block = allocator->freelist;
while (block != NULL && (block->size < size || !block->is_free)) {
block = block->next;
}
// If no suitable block was found, return NULL
if (block == NULL) {
return NULL;
}
// Split the block into two blocks if the block is larger than needed
if (block->size > size) {
// Create a new block for the remainder
buddy_block_t *remainder = (buddy_block_t *) ((uint8_t *) block + size);
remainder->size = block->size - size;
remainder->is_free = true;
remainder->next = block->next;
// Update the current block
block->size = size;
block->next = remainder;
}
// Mark the block as allocated and return a pointer to the memory
block->is_free = false;
return (void *) (block + 1);
}
void
buddy_free(buddy_allocator_t * allocator, void *ptr)
{
// Get a pointer to the block header
buddy_block_t *block = (buddy_block_t *) ptr - 1;
if (block->is_free) {
return;
}
// Mark the block as free
block->is_free = true;
// Try to merge the block with its buddy (if it has one and the buddy is free)
size_t block_size = block->size;
buddy_block_t *buddy = (buddy_block_t *) ((uint8_t *) block + block_size);
// Check if the buddy block is within the memory region managed by the allocator
if (block < allocator->freelist || block > (buddy_block_t *) ((uint8_t *) allocator->freelist + allocator->total_size) || buddy < allocator->freelist || buddy > (buddy_block_t *) ((uint8_t *) allocator->freelist + allocator->total_size)) {
// One of the blocks is outside of the memory region managed by the allocator, so they cannot be merged
return;
}
// Check if the buddy block is free and has the same size as the current block
if (buddy->is_free && buddy->size == block_size) {
// The buddy is free and has the same size as the current block, so they can be merged
if (buddy < block) {
// The buddy comes before the current block in memory, so it should be the new block
buddy->size *= 2;
buddy->next = block->next;
block = buddy;
}
else {
// The current block comes before the buddy in memory, so it should be the new block
block->size *= 2;
block->next = buddy->next;
}
}
// Insert the merged block back into the free list
buddy_block_t *prev = NULL;
buddy_block_t *curr = allocator->freelist;
while (curr != NULL && curr < block) {
prev = curr;
curr = curr->next;
}
block->next = curr;
if (prev == NULL) {
allocator->freelist = block;
}
else {
prev->next = block;
}
}
void
initme(buddy_allocator_t *ctl)
{
#if 0
static buddy_block_t block;
static char mem[1024 * 1024];
memset(&block,0,sizeof(block));
block.size = sizeof(mem);
block.is_free = 1;
ctl->total_size = block.size;
ctl->freelist = █
ctl->min_block_size = 128;
#else
static char mem[1024 * 1024];
buddy_block_t *block = (void *) mem;
memset(block,0,sizeof(*block));
block->size = sizeof(mem) - sizeof(*block);
block->is_free = 1;
ctl->total_size = block->size;
ctl->freelist = block;
ctl->min_block_size = 128;
#endif
}
// Test the behavior of the buddy_alloc function when it is unable to fulfill an allocation request due to insufficient free memory
void
test_buddy_alloc_insufficient_memory()
{
// Allocate all of the available memory
buddy_allocator_t allocator = { 0 };
initme(&allocator);
void *ptr = buddy_alloc(&allocator, allocator.total_size);
assert(ptr != NULL);
// Attempt to allocate more memory
ptr = buddy_alloc(&allocator, 1);
assert(ptr == NULL);
}
// Test the behavior of the buddy_alloc function when it is called with a size of 0
void
test_buddy_alloc_size_zero()
{
buddy_allocator_t allocator = { 0 };
initme(&allocator);
// Attempt to allocate a block of size 0
void *ptr = buddy_alloc(&allocator, 0);
assert(ptr == NULL);
}
int
main(void)
{
test_buddy_alloc_insufficient_memory();
test_buddy_alloc_size_zero();
return 0;
}
Related
I'm building my own memory allocator and my programs are segfaulting because of my splitting ( when a block is allocated, splitting into two block one with data allocated and one with the rest of the free memory not used) and of my merging ( merging neighbor free memory slots ) and I just can't figure out where the problem ism any help is appreciated.
Here is my splitting method:
struct mem_block *split_block(struct mem_block *block, size_t size)
{
if(block->free){
char *block_address = (char *)block;
struct mem_block *second_block = (struct mem_block *)(block_address + size);
second_block->size = block->size - size;
block->size = size;
second_block->region_id = block->region_id;
snprintf(second_block->name, 32, "Allocation: %lu\n", g_allocations++);
if(block->next != NULL){
second_block->next = block->next;
second_block->prev = block;
block->next = second_block;
}
else{
block->next = second_block;
second_block->prev = block;
second_block->next = NULL;
g_tail = second_block;
}
LOG("Split completed; old block address = %p, new block address = %p\n", block, second_block);
return second_block;
}
else{
return NULL;
}
}
Here is my merging method:
struct mem_block *merge_block(struct mem_block *block)
{
if(g_head == NULL && g_tail == NULL){
block->next = NULL;
block->prev = NULL;
g_head = block;
g_tail = block;
return g_head;
}
else {
g_tail->next = block;
block->prev = g_tail;
block->next = NULL;
g_tail = block;
return g_tail;
}
return NULL;
}
Here is my memory block structure:
struct mem_block {
/**
* The name of this memory block. If the user doesn't specify a name for the
* block, it should be auto-generated based on the allocation ID. The format
* should be 'Allocation X' where X is the allocation ID.
*/
char name[32];
/** Size of the block */
size_t size;
/** Whether or not this block is free */
bool free;
/**
* The region this block belongs to.
*/
unsigned long region_id;
/** Next block in the chain */
struct mem_block *next;
/** Previous block in the chain */
struct mem_block *prev;
/**
* "Padding" to make the total size of this struct 100 bytes. This serves no
* purpose other than to make memory address calculations easier. If you
* add members to the struct, you should adjust the padding to compensate
* and keep the total size at 100 bytes; test cases and tooling will assume
* a 100-byte header.
*/
char padding[35];
} __attribute__((packed));
Here is the malloc function where split is called:
void *malloc(size_t size)
{
pthread_mutex_lock(&alloc_mutex);
size_t total_size = size + sizeof(struct mem_block);
size_t aligned_size = total_size;
if (total_size % 8 !=0) {
aligned_size = (total_size / 8) * 8 + 8;
}
LOG("Allocation: request size = %zu, total size = %zu, aligned size = %zu\n",
size, total_size, aligned_size);
struct mem_block *reused_block = reuse(aligned_size);
if(reused_block != NULL){
pthread_mutex_unlock(&alloc_mutex);
return reused_block + 1;
}
int page_size = getpagesize();
size_t num_pages = aligned_size / page_size;
if(aligned_size % page_size != 0){
num_pages++;
}
size_t region_size = num_pages * page_size;
struct mem_block *block = mmap(NULL, region_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(block == MAP_FAILED){
perror("mmap");
pthread_mutex_unlock(&alloc_mutex);
return NULL;
}
snprintf(block->name, 32, "Allocation %lu", g_allocations++);
block->size = region_size;
block->free = true;
block->region_id = g_regions++;
LOG("Name: %s\n", block->name);
if(g_head == NULL && g_tail == NULL){
block->next = NULL;
block->prev = NULL;
g_head = block;
g_tail = block;
}
else {
g_tail->next = block;
block->prev = g_tail;
block->next = NULL;
g_tail = block;
}
split_block(block, aligned_size);
block->free = false;
pthread_mutex_unlock(&alloc_mutex);
return block+1;
}
Here is the free function where merge is called:
void free(void *ptr)
{
pthread_mutex_lock(&alloc_mutex);
LOG("Free request; address = %p\n", ptr);
if (ptr == NULL) {
pthread_mutex_unlock(&alloc_mutex);
return;
}
struct mem_block *block = (struct mem_block *) ptr-1;
block->free = true;
if(block->prev != NULL){
block->prev->next = block->next;
}
if(block->next != NULL){
block->next->prev = block->prev;
}
if(g_head == block){
g_head = block->next;
}
if(g_tail == block){
g_tail = block->prev;
}
int ret = munmap(block, block->size);
if (ret == -1){
perror("munmap");
pthread_mutex_unlock(&alloc_mutex);
return;
}
merge_block(block);
pthread_mutex_unlock(&alloc_mutex);
return;
}
I have school project to create memory allocator. I´ve been debugging it over 3 days now with no reasonable outcome. It is suddenly failing when higher number is ment to be allocated for example i have an array of 65000Bytes and I want to allocate 12000, it fails. Lower numbers up to 800 work great tho.
Let´s say we have static array consisting of 65000Bytes.
We call init, which creates linked list which has pointer to next list and size of list. We also are allowed to have one global variable for pointer to start of array I named mine "start".
Looks like this:
typedef struct mallocstr head;
char* start;
struct mallocstr
{
head* next; //For moving through list
int size; //If allocated then value is <0
};
And here is my allocator function:
void* memory_alloc(unsigned int size)
{
head* p = start;
char* endd= end();
while (p != NULL)
{
if (p->size > 0 && p->size >= size + sizeof(p) && size != 0)
{
int newsize = p->size - size - sizeof(p);
//If head is smaller than newsize create next block and allocate this one
if (sizeof(p) < newsize)
{
hlavicka* var;
p->size = (p->size - newsize) * (-1);
int point = p->size;
point*= -1;
p->next= p + sizeof(p) + point;
var= p;
p = p->next;
p->size= newsize;
p->next = NULL;
return (void*)var + 2*(sizeof(int));
}
//If head is greater or same as newsize
else if (sizeof(p) >= newsize)
{
p->size= p->size* (-1);
p->next = NULL;
return (void*)p + 2*(sizeof(int));
}
}
//If we are unable to alocate this block because size is too small or it is allocated we move to
//next one
else if (p->size< size + sizeof(p) && p != endd|| p->size< 0)
{
p = p->next;
}
//When we cannot allocate any block
else if (p->size < size + sizeof(p) && p == endd|| size == 0)
{
return NULL;
}
}
}
Function end is for getting pointer to the end of list. Here it is:
void* end()
{
head* p = start;
while (p != NULL)
{
if (p->next== NULL)
{
break;
}
else
p = p->next;
}
return (void*)p;
}
i had to write my own free & malloc function.
So far I have not had a problem with that, but now I am supposed to merge neighboring free memory blocks in the halde_free() function. I would be really grateful if you could help me there.
#include "halde.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
/// Magic value for occupied memory chunks.
#define MAGIC ((void*)0xbaadf00d)
/// Size of the heap (in bytes).
#define SIZE (1024*1024*1)
/// Memory-chunk structure.
struct mblock {
struct mblock *next;
size_t size;
char memory[];
};
/// Heap-memory area.
char memory[SIZE];
/// Pointer to the first element of the free-memory list.
static struct mblock *head;
/// Helper function to visualise the current state of the free-memory list.
void halde_print(void) {
struct mblock* lauf = head;
// Empty list
if ( head == NULL ) {
fprintf(stderr, "(empty)\n");
return;
}
// Print each element in the list
while ( lauf ) {
fprintf(stderr, "(addr: 0x%08zx, off: %7zu, ", (uintptr_t) lauf, (uintptr_t)lauf - (uintptr_t)memory);
fflush(stderr);
fprintf(stderr, "size: %7zu)", lauf->size);
fflush(stderr);
if ( lauf->next != NULL ) {
fprintf(stderr, " --> ");
fflush(stderr);
}
lauf = lauf->next;
}
fprintf(stderr, "\n");
fflush(stderr);
}
void *halde_malloc (size_t size) {
static int initialized = 0;
if(initialized == 0){
head = (struct mblock *) memory;
head->size = sizeof(memory) - sizeof (struct mblock);
head->next = NULL;
initialized = 1;
}
if(size == 0){
return NULL;
}
struct mblock *lauf = head;
struct mblock **prev_next = &head;
while (lauf != NULL && lauf->size < size){
prev_next = &(lauf->next);
lauf = *prev_next;
}
if(lauf == NULL){
errno = ENOMEM;
return NULL;
}
if((lauf->size -size) <= sizeof(struct mblock)){
*prev_next = lauf->next;
} else {
//mblock anlegen und init.
struct mblock* neu = (struct mblock*) (lauf->memory + size);
neu->size = lauf->size - sizeof(struct mblock) - size;
neu->next = lauf->next;
//mblock anpassen
lauf->size = size;
//verketten wiederherstellen
*prev_next = neu;
}
lauf->next = MAGIC;
return lauf->memory;
}
void halde_free (void *ptr) {
if(ptr == NULL){
return;
}
struct mblock *mbp = (struct mblock *) ptr - 1;
if(mbp->next != MAGIC){
abort();
} else {
mbp->next = head;
head = mbp;
}
}
The code works so far but i have really no idea how to merge blocks..
The memory management runs over a simply linked lists. The variable head points to the first free memory block.
My idea is to merge the blocks directly in the else part but i don't have a good idea to do that..
I try to write my own custom malloc and free function in c. I worked around 12 hours on this and tried lots of things. But it doesn't work.
Maybe you guys can figure out the error. Allocated memory gets removed from the list with a next pointer to a specific address to identify it later in the free function. The current error is a segmentation fault 11 in the split method.
C-File:
Head:
#define MAGIC ((void*)0xbaadf00d)
#define SIZE (1024*1024*1)
typedef struct mblock {
struct mblock *next;
size_t size;
char memory[];
}mblock;
char memory[SIZE];
static struct mblock *head;
malloc:
void *halde_malloc (size_t size) {
printf("Starting\n");
printf("%zu\n",size);
if(size <= 0) {return NULL;}
if(head == NULL){
initializeBlock();
printf("Memory initialized\n");
}
mblock *temp_block = head;
while(temp_block != NULL) {
printf("IN\n");
if(temp_block->size == size) {
list_remove(temp_block);
temp_block->next = MAGIC;
return (void*)(temp_block);
} else if(temp_block->size > size) {
size_t temp_size = temp_block->size;
printf("size IS more than equal\n");
list_split_AND_Remove(temp_size - size, temp_block);
temp_block->size = size;
temp_block->next = MAGIC;
return (void*)(temp_block);
}
temp_block = temp_block->next;
printf("One block checked\n");
}
errno = ENOMEM;
return NULL;
}
Initialize:
void initializeBlock(){
printf("Initializing\n");
head = (mblock*)memory;
head->size=sizeof(memory)-sizeof(mblock);
head->next=NULL;
}
Split:
void list_split_AND_Remove(size_t size, mblock *lastBlock) {
printf("Split\n");
mblock *new = (void*)((mblock*)lastBlock+size+sizeof(mblock));
new->size = size - sizeof(mblock);
new->next = lastBlock->next;
lastBlock->next = new;
printf("START REMOVE");
list_remove(lastBlock);
}
Remove:
void list_remove(mblock *p) {
printf("Remove\n");
mblock *temp_block = head;
if(p == head) {
if(head->next == NULL) {
head = NULL;
return;
} else {
head = p->next;
return;
}
}
while(temp_block->next != NULL) {
if(temp_block->next == p) {
printf("Found P:");
temp_block = p->next;
return;
}
temp_block = temp_block->next;
}
}
Free:
void halde_free (void *ptr) {
printf("FREE\n");
mblock *new_block = ptr;
if(new_block->next == MAGIC) {
new_block->next = head;
head = new_block;
} else {abort();}
}
Issues with your code include, but are not necessarily limited to:
list_remove() does not actually remove the specified block from the list unless it happens to be the current list head. In every other case, therefore, halde_malloc() corrupts the list after calling list_remove() when it modifies the node's next pointer.
list_split_AND_Remove() performs incorrect pointer arithmetic. Specifically, mblock *new = (void*)((mblock*)lastBlock+size+sizeof(mblock)); does not do what you appear to want to do, because pointer arithmetic operates in units the size of the pointed-to type, whereas the size argument and the result of the sizeof operator have units of individual bytes. (Also, both casts are useless, albeit not harmful in themselves.)
Your allocator returns a pointer to the block header, not to its data. As a result, the user will very likely overwrite the block header's contents, leading to havoc when you later try to free that block.
You seem to assume that mblock objects have an alignment requirement of 1. That might not be true.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have spotted down an error of seg fault, which occurred to be in my divideBlock() function. When I dereferenced newBlock to access info, i.e. without assigning value to it but just dereferencing it, it was alright, but when I change its value, I received a set fault. Any idea why this would happen? Could it be because of the address manipulation and non-standard pointer access? If so, what should I do if I want to break one block into two?
typedef struct freeBlock
{
size_t info;
struct freeBlock *next;
} freeBlock;
freeBlock *divideBlock(freeBlock *block, size_t reqSize)
{
// Declaration of variables.
freeBlock *newBlock;
size_t blockSize;
blockSize = block->info >> 1;
newBlock = block + reqSize;
newBlock->info = (blockSize - reqSize) << 1; // new block marked as unused. seg fault happens here!!!
block->info = (reqSize << 1) | 1; // old block marked as used.
return newBlock;
}
void *malloc(size_t size)
{
if (size == 0)
return NULL;
// Declaration of variables.
size_t blockSize, occpd, poccpd, reqSize;
freeBlock *curr, *prev, *newBlock, *allocd, *combined;
printf("%d", __LINE__);
reqSize = (size + sizeof(size_t) + sizeof(char*) + padding + (align - 1)) & ~ (align - 1);
printf("%d", __LINE__);
curr = head;
prev = NULL;
while (curr != NULL)
{
printf("%d", __LINE__);
occpd = curr->info & 1;
if (prev != NULL)
{
printf("%d", __LINE__);
poccpd = prev->info & 1;
if (!poccpd && !occpd)
{
combined = combineBlock(prev, curr);
if (combined)
curr = combined;
}
}
blockSize = curr->info >> 1;
printf("%d", __LINE__);
if (blockSize >= reqSize && !occpd)
{
if (blockSize >= 2 * reqSize)
{
newBlock = divideBlock(curr, reqSize);
if (newBlock != NULL)
{
newBlock->next = curr->next;
curr->next = newBlock;
}
}
curr->info |= 1;
return curr + sizeof(char*) + sizeof(size_t);
}
prev = curr;
curr = curr->next;
}
printf("%d", __LINE__);
allocd = sbrk(reqSize * 3);
if (allocd == (void*)-1)
return NULL;
allocd->info = ((reqSize * 3) << 1) | 1;
newBlock = divideBlock(allocd, reqSize);
newBlock->next = NULL;
allocd->next = newBlock;
if (head == NULL)
head = allocd;
else
curr = allocd;
return allocd + sizeof(char *) + sizeof(size_t);
}
The problem seems to be the line:
newBlock = block + reqSize;
newBlock will point to a location (address) which is "location-of-block + reqSize*sizeof(freeBlock)"
Probably the intention is simply that newBlock shall point to the location reqSize bytes after block.
To increment a pointer by 1 you can cast it to char* before adding reqSize.
Maybe something like this for the divide:
freeBlock *divideBlock(freeBlock *block, size_t reqSize)
{
// Declaration of variables.
freeBlock *newBlock;
size_t blockSize;
blockSize = block->info >> 1;
newBlock = (freeBlock*)(((char*)block) + reqSize);
newBlock->info = (blockSize - reqSize) << 1;
block->info = (reqSize << 1) | 1; // old block marked as used.
return newBlock;
}
but you also have problems in malloc function where you add numbers to pointers of freeBlock type. Probably not what you want.
BTW:
Why do you use
sizeof(char *) + sizeof(size_t)
Shouldn't that be
sizeof(freeBlock)