Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom memory allocator

I wrote a custom memory allocator. It has 2 restrictions that I want to remove so it works like malloc/free.

1.) The mem_free call requires a cast to an unsigned char * for its input parameter. I would like it to take a pointer of any type. How can this be done?

2.) The memory allocator I wrote allocates a block of memory to the front of the buffer and it also writes its size. The free function removes the last block of allocated memory in the buffer. So the order of the malloc/free calls matter or it will not work. How can I remove this restriction?

want to be able to do this:

char* ptr1 = mem_alloc(10);
char* ptr2 = mem_alloc(4);

mem_free(ptr1);
mem_free(ptr2);

have to do this now:

char* ptr1 = mem_alloc(10);
char* ptr2 = mem_alloc(4);

mem_free(ptr2);
mem_free(ptr1);

code:

unsigned char* mem_alloc(unsigned int size) {
    unsigned int s;
    if( (size + MEM_HEADER_SIZE)  > (MEM_MAX_SIZE - mem_current_size_bytes) ) {
        return NULL;
    }
    if(is_big_endian() == 0) {
        s = (mem_buff[3] << 24) + (mem_buff[2] << 16) + (mem_buff[1] << 8) + mem_buff[0];
    } else {
        s = (mem_buff[0] << 24) + (mem_buff[1] << 16) + (mem_buff[2] << 8) + mem_buff[3];
    }
    memcpy(mem_buff + mem_current_size_bytes, &size, sizeof(unsigned int));
    unsigned char* result = mem_buff + (mem_current_size_bytes + MEM_HEADER_SIZE);
    mem_current_size_bytes += MEM_HEADER_SIZE + size;
    return result;
}

void mem_free(unsigned char* ptr) {
    unsigned int i,s;
    for(i=0; i<mem_current_size_bytes; i++) {
        if( (char*)ptr == (char*)(mem_buff + i) ) {
            if(is_big_endian() == 0) {
                s = (*(ptr - 1) << 24) + (*(ptr - 2) << 16) + (*(ptr - 3) << 8) + *(ptr - 4);
            } else {
                s = (*(ptr - 4) << 24) + (*(ptr - 3) << 16) + (*(ptr - 2) << 8) + *(ptr - 1);
            }
            mem_current_size_bytes-=s;
            mem_current_size_bytes-=MEM_HEADER_SIZE;
            break;
        }
    }
}
like image 554
eat_a_lemon Avatar asked Jul 03 '11 17:07

eat_a_lemon


1 Answers

1) Use a void* instead.
2) Store a map of addresses to allocated blocks and a seperate map of unallocated blocks. You can then look up which block is being freed in the allocated map, remove it and then add the block to the unallocated map (making sure to merge it with any free blocks either side of it). Of course, this can and does lead to memory fragmentation but that is rather unavoidable really.

like image 80
Goz Avatar answered Oct 04 '22 13:10

Goz