Weird behavior of mallocr() function

Jeff Johnston
Wed Jan 6 20:09:00 GMT 2010

On 05/01/10 03:39 AM, Denis Micolani wrote:
>> For starters, your linker script is restricting the heap to be 0x400 bytes
>> (1024).  That is less that 1344 so your return code makes sense. Malloc
>> creates bins to reuse for small allocations so if you are really this
>> constrained for space, you won't be able to use the malloc logic in newlib
>> and will have to override it.
> It seems kinda weird to me that malloc is asking an allocation for
> about 1.34Kbytes while I'm just asking for 1 byte. Anyway if that's
> the way it works, I got nothing to complain about, I'll just expand
> the heap area in the linker script to be a bit larger.

The algorithm is trying to balance speed and storage usage as well as 
minimize fragmentation.  The point of the fixed-size bins is that when 
you ask for small amounts of storage, it doesn't go to the external 
pool.  Instead, it has a reusable set of slots that can be quickly 
accessed/reused and it doesn't have to waste bytes on overhead (slot is 
free or taken which  can be tracked with a single bit).  Imagine if you 
instead always called sbrk for storage and asked for 1000 bytes then 1 
byte, then another 1000.  If you free both of the 1000 byte blocks, you 
can't reclaim the 2000+ bytes together until the 1 byte block is freed. 
  The one byte block here is actually taking up more space due to the 
overhead of keeping track of it.  If you free n 1 byte blocks in a row, 
combining them together still doesn't net you much.  If the really small 
stuff is kept off in the bins, everything left is worth recombining 
after freeing to get larger areas.

>> As well, your current code isn't going to work.  You are adding incr to
>> heap_start and comparing this to heap_end (i.e. neither changes).  I'm
>> pretty sure you meant to use heap_current_end in your if statement.
>> As well, if you are going to have a reentrant version, you might as well set
>> errno properly using the reentrant struct that is input.
>> See newlib/libc/include/sys/errno.h for the __errno_r macro.
> Thanks for pointing that out!
>> Most sbrk implementations use the logic found in libgloss/libnosys/sbrk.c
>> which has the heap and stack going in opposite directions and allocates a
>> lump sum for the two in the linker script. This allows peaks for either the
>> stack or heap as long as the total is within limits.  You might want to
>> check out this design before implementing your own.
> I did not realize there were such a directory with all those useful
> functions within, thanks for pointing this out too!
> Just one more question: AFAIK, in order to get malloc to be reentrant,
> I should provide my own stubs to lock and unlock the memory, these
> should be: __malloc_unlock() and __malloc_lock().
> Anyway if I define them just like other stubs in the global scope I
> get the compiler to fail, saying that there are multiple definitions
> of those. Specifically, saying that they were already defined in
> newlib-1.18.0/newlib/libc/stdlib/mlock.c .So, how could I manage to
> get it to work? Should I place my own stub directly in newlib's source
> code and recompile it (it doesn't seem to me like a good idea) ?

Normally, a platform has its own libc/machine subdirectory.  Files there 
are used to override the ones in the shared directories of newlib.  For 
example, if you have a libc/machine/XXX directory and put your own 
mlock.c file there, it will override the one in stdlib (where XXX is the 
name of your platform).  There are plenty of examples in the newlib 
repository under libc/machine.  You have to specify this in  There are instructions on the newlib web-site in the 
FAQ section.

-- Jeff J.

More information about the Newlib mailing list