Quick actions

cmd+k|ctrl+k

Navigation

Languages

Dynamic_Alloc

Snippet info

Language

C

Visibility

public

Author

evine

Created

2022-05-24T21:26:59.024213Z

Updated

2022-05-31T17:39:24.464509Z

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>

#define DYNAMIC_ALLOC_SIGNATURE_USED ((size_t)0xA888A8A8A8A8A0A8)
#define DYNAMIC_ALLOC_SIGNATURE_FREE ((size_t)0x8880A0A8A0A0A088)
#define DYNAMIC_ALLOC_SIGNATURE_BITS ((size_t)0x2008080008080020)

typedef struct Dynamic_Alloc_Preamble Dynamic_Alloc_Preamble;
struct Dynamic_Alloc_Preamble {
    Dynamic_Alloc_Preamble *next;
    size_t is_allocated;
};

size_t mem_pool_raw[4096 * 4 / sizeof(size_t)];
char *mem_pool = (char *)mem_pool_raw;
Dynamic_Alloc_Preamble *mem_next = (Dynamic_Alloc_Preamble *)mem_pool_raw;

void dynamic_print() {
    Dynamic_Alloc_Preamble *preamble = (Dynamic_Alloc_Preamble *)mem_pool;
    size_t used_mem = 0;
    size_t free_mem = 0;
    size_t used_blocks = 0;
    size_t free_blocks = 0;
    while(true) {
        if(preamble->is_allocated == 0) {
            break;
        } else if(preamble->is_allocated == DYNAMIC_ALLOC_SIGNATURE_USED) {
            used_mem += (char *)preamble->next - (char *)preamble; 
            used_blocks += 1;
        } else if(preamble->is_allocated == DYNAMIC_ALLOC_SIGNATURE_FREE) {
            free_mem += (char *)preamble->next - (char *)preamble; 
            free_blocks += 1;
        }
        
        preamble = preamble->next;
    }
    
    printf("Total Mem: %zu, Blocks: %zu\n", used_mem + free_mem, used_blocks + free_blocks);
    printf("Used  Mem: %zu, Blocks: %zu\n", used_mem, used_blocks);
    printf("Free  Mem: %zu, Blocks: %zu\n", free_mem, free_blocks);
}

void dynamic_defrag() {
    mem_next = (Dynamic_Alloc_Preamble *)mem_pool_raw;
}

void dynamic_atomic_store(size_t *t, size_t v) {
    *t = v;
}

void *dynamic_alloc(size_t size) {
    size_t mask_size = sizeof(size_t) * 2 - 1;
    size_t allocation_size = (size + sizeof(Dynamic_Alloc_Preamble) + mask_size) & ~mask_size;
    
    Dynamic_Alloc_Preamble *preamble = mem_next;
    while(true) {
        if(preamble->is_allocated == 0) {
            break;
        } else if(preamble->is_allocated == DYNAMIC_ALLOC_SIGNATURE_USED) {
            preamble = preamble->next;
            continue;
        } else if(preamble->is_allocated == DYNAMIC_ALLOC_SIGNATURE_FREE) {
            Dynamic_Alloc_Preamble *next_used_preamble = preamble->next;
            while(true) {
                if(next_used_preamble->is_allocated == 0) {
                    preamble->next = 0;
                    preamble->is_allocated = 0;
                    goto continue_outer;
                } else if(next_used_preamble->is_allocated == DYNAMIC_ALLOC_SIGNATURE_USED) {
                    preamble->next = next_used_preamble;
                    break;
                } else if(next_used_preamble->is_allocated == DYNAMIC_ALLOC_SIGNATURE_FREE) {
                    next_used_preamble = next_used_preamble->next;
                    continue;
                }
                
                assert(0 && "heap corruption");
                return 0;
            }
            
            if(allocation_size <= (size_t)next_used_preamble - (size_t)preamble)
                break;
            
            preamble = preamble->next;
            continue_outer: continue;
        }
        
        assert(0 && "heap corruption");
        return 0;
    }
    
    preamble->next = (Dynamic_Alloc_Preamble *)((char *)preamble + allocation_size);
    mem_next = preamble->next;
    dynamic_atomic_store(&preamble->is_allocated, DYNAMIC_ALLOC_SIGNATURE_USED);
    
    return (void *)(preamble + 1);
}

void dynamic_dealloc(void *ptr) {
    Dynamic_Alloc_Preamble *preamble = (Dynamic_Alloc_Preamble *)ptr - 1;
    size_t signature = preamble->is_allocated;
    if((signature & ~DYNAMIC_ALLOC_SIGNATURE_BITS) == DYNAMIC_ALLOC_SIGNATURE_FREE)
    {
        if((signature & DYNAMIC_ALLOC_SIGNATURE_BITS) == DYNAMIC_ALLOC_SIGNATURE_BITS) {
            preamble->is_allocated = DYNAMIC_ALLOC_SIGNATURE_FREE;
            return;
        } else {
            // Double free
            assert(0 && "double dealloction\n");
            return;
        }
    }
    
    assert(0 && "heap corruption");
}

int main(int argc, char **argv) {
    int *a1 = dynamic_alloc(4);
    int *b1 = dynamic_alloc(4);
    int64_t *c1 = dynamic_alloc(8);
    void *d1 = dynamic_alloc(0);
    
    dynamic_dealloc(a1);
    dynamic_dealloc(b1);
    dynamic_dealloc(c1);
    //dynamic_dealloc(d1);
    
    dynamic_defrag();
    
    int *a2 = dynamic_alloc(4);
    int64_t *c2 = dynamic_alloc(256);
    dynamic_defrag();
    int64_t *e1 = dynamic_alloc(8);
    dynamic_dealloc(e1);
    
    dynamic_print();
    return 0;
}
INFO