Reputation: 139
I have a barebone arm controller compiled with the gcc-arm-none-eabi toolchanin. I notice that asking malloc() for 132 bytes which in turn causes malloc() to call sbrk() twice, first asking for size 152 B and next asking for 4100 B before returning.
Malloc() is in this case called from sprintf(), and it seem that each formatter (%d, %f, ...) allocates its own memory. Repeted use of one identifier does not result in more allocation. It is when %f is used that the 4100 B is allocated.
4 kB is in this case not a problem. But I would like to know that it does not ask for another similar amount.
Should malloc allocate this much?
Is there anything I can set to prevent it?
Should I worry that malloc might ask for even more space (without reason)?
The sbrk code is not the one provided from the toolchain. malloc is wrapped so I can see what happens.
char *_cur_brk;
void *_sbrk_r(struct _reent *reent, ptrdiff_t diff)
{
void *_old_brk = _cur_brk;
monitor_printf("_sbrk_r called with size = %d. cur_brk = %p \t", diff, _cur_brk);
void * ptr;
ptr = __builtin_return_address(0);
monitor_printf("Called from %d: %p\t", 0, ptr );
monitor_printEOL();
extdiff = diff;
if ( (_cur_brk + diff ) > _HeapLimit ) {
sbrk_error += 1;
errno = ENOMEM;
monitor_printf(" failed, cur_brk=%d, HeapLimit=%d", _cur_brk, _HeapLimit);
monitor_printEOL();
return (void *)-1;
}
sbrk_error = 0;
_cur_brk += diff;
monitor_printf("return %p", _old_brk);
monitor_printEOL();
return _old_brk;
}
void * __wrap__malloc_r( struct _reent *reent, size_t size )
{
void * ret;
monitor_printf("wrap_malloc_r called with size = %d.", size);
monitor_printEOL();
ret = __real__malloc_r( reent, size );
return ret;
}
output of call to malloc(132)
wrap_malloc_r called with size = 132.
_sbrk_r called with size = 152. cur_brk = 0x20005f64 Called from 0: 0x801311b
return 0x20005f64
_sbrk_r called with size = 4100. cur_brk = 0x20005ffc Called from 0: 0x8013181
return 0x20005ffc
Memory allocated at 0x20005f70lling malloc(132)
thanks /johan
Upvotes: 3
Views: 388
Reputation: 399833
"Without reason" is a bold claim, I'm sure it's not doing it just to be mean.
What you should do, however, is investigate if you can move to a more embedded-friendly standard library, one that is more careful with memory. It seems its your heap allocation code, i.e. the malloc()
implementation that's the culprit.
One simple guess is that malloc()
needs some data structure to keep track of the allocations, and since you're (probably, remember this is a guess!) doing the first allocation as a side-effect of vsnprintf()
, it has to do that in order to track it.
On more typical desktop/server computer platforms of today, 4 KB is very little memory so no reason to not do the allocation if it's needed by the design. In the embedded space, of course, that's not true.
Personally, I have a local replacement for vsnprintf()
that does zero heap allocations.
Upvotes: 2