Robert Seczkowski wrote:
I would like to recall my problem with malloc function.
Because I didn't receive answer even touching the problem.
It's hard for me to understand, that so many people writing to this group are not using malloc function. It's like diving with tied legs and hands.

hehe, it's hard for _me_ to understand that somebody even considers the use of malloc on a small MCU ;-) realy, i never used malloc until now, and i dont think that i'll use it in the near future. projects on such small CPUs rarely use dynamic memory allocation, the application isn't that dynamic and complex. in rare cases where the number of entries (of some data) changes, then an array is often better, storing how much entries are allocated, or flags for each entry. that has the advantage of a small overhead, beeing predictable - you can exactly calcualte how much memory it consumes in the worst case. its can also be smaller, because an index in an array can be a byte, not a word (sizeof(void *)). and a simple (index < MAX_NUM_OF_ENTRIES) can be your size check, if there are free entries left.


The two things where considred:
1. malloc occupies space of noinit section !!

it has to occupy space, somewhere...
the size is usualy not known at link time, that means its at the end of all other allocated RAM. the .noinit section is the last section in RAM. are you sure that its allocated IN .noinit and not right BEHIND that section? (.noinit has probably the a size of 0, unless you actively put data in there)

2. malloc collide with stack after reallocating several times.

hm. RE-allocating, if that is freeing a chunk and then allocating one of the exact same size, it probably should not grow, but use the same chunk again. i'd say its preferable if it would not grow, but as that would work in a special case only, i dont see its importance. (if you want to make it good, also add a garabge collector and defrag the free memory, in any other case you will end up with unused, unusable, memory holes. of course that does not work with simple pointers, you need more, ... hm where are my 4kB flash and 256 bytes RAM are gone)

in any other case, it grows upwards, stack grows downwards, neither has a size check (as usualy in the C world) and a collision is the natural end of overallocating.

These faults are serious and should not be avoided.
The problems were solved in attached code.
Please test it and let me know how is going.

hm, your GET_HEAP_BOTTOM macro just copies the pointer to the stack at the current moment. what about interrupts, other subroutines that use more stack? where does your 20 bytes securiry margin come from? (fantasy number?;-) i'd sugest to add a comment to the code, describing why your subtracting 20 at all and why it has to be 20.

whats that "once" stuff? you know, you can initialize static variables too? yes, they are initialized only once, and not on each function entry (they would loose their usefulness of beeing static if it were different..)

chris

------------------------------------------------------------------------

#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);
        heap_next = &heap_top[xsize + 1];

        
                if (xsize == 0x7ff)//(xsize<<1)+2 == 0)
        {
            f = 1;
        }else if(heap_next >= heap_bottom){
                f = -1;
                }

        if (FREE_P (heap_top))
        {
            if (f>0)
            {
                xsize = heap_bottom - heap_top - 1;
            }
                        else if (f < 0){
                        *heap_top = (heap_bottom - heap_top - 1) << 1;
                        xsize = XSIZE (heap_top);
                        }
            else if (FREE_P(heap_next))
            {
                *heap_top = ( (XSIZE(heap_next) == 0x7FF)//<<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);
}




Reply via email to