Lately I found the bug in my mymalloc function. Change really is in below lines: if (xsize == 0x7FFF) f = 1; //was (xsize<<1)+2 == 0) // 0x7FFF means empty else{ heap_next = &heap_top[xsize + 1]; 1: if(heap_next >= heap_bottom ) f = 1;//f=1 mean do loop once and end if you reach over stack }
The basic disadvantage of below code is the way of description bit allocation. When You overrun buffer you almost loose all data ie: char * buffer = "abcd"; char* ptr = mymalloc(4); //you overrun buffer because '\0' deletes next and all above allocations. Moreover this improvement prevents deleting stack. however I have no idea where to put malloc information data. All ideas have pros and cons. all code is below: //released under GNU PUBLIC LICENCE #include <stdlib.h> #define XSIZE(x) ((*x)>>1) #define FREE_P(x) (!((*x)&1)) #define MARK_BUSY(x) ((*x)|=1) #define MARK_FREE(x) ((*x)&=0xfffe) //extern size_t __bss_end; extern size_t __noinit_end; #define GET_HEAP_BOTTOM(__x) __asm__ __volatile__("mov r1, %0": "=r" ((uint16_t)__x) :) void myfree (void *p); void *mymalloc (size_t size); void *mymalloc (size_t size) { static char once; size_t * heap_bottom; size_t * heap_top = &__noinit_end; size_t * heap_next; size_t xsize; char f = 0; if (!once) { once = 1; *heap_top = 0xFFFE; } GET_HEAP_BOTTOM (heap_bottom); heap_bottom -= 20; size = (size+1)>>1; /* round to 2 */ do { xsize = XSIZE (heap_top); if (xsize == 0x7FFF) f = 1; //(xsize<<1)+2 == 0) else{ heap_next = &heap_top[xsize + 1]; if(heap_next >= heap_bottom ) f = 1; } if (FREE_P (heap_top)) { if (f>0) { xsize = heap_bottom - heap_top - 1;//(heap_b - heap_t)/2 in fact } else if (FREE_P(heap_next)) { *heap_top = ( (XSIZE(heap_next)== 0x7FFF)/*<<1) + 2 == 0*/ ? 0xFFFE : (xsize + XSIZE(heap_next) + 1)<<1); continue; } if (xsize >= size) { if (f>0) heap_top[size + 1] = 0xFFFE; else if (xsize != size) heap_top[size + 1] = (xsize - size - 1) << 1; *heap_top = size << 1; MARK_BUSY (heap_top); return heap_top+1; } } heap_top += xsize + 1; } while (!f); return NULL; } void myfree (void *p) { size_t *t = (size_t*)p - 1; MARK_FREE (t); }