This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Weird behavior of mallocr() function
- From: Denis Micolani <micorulez at gmail dot com>
- To: newlib at sources dot redhat dot com
- Date: Sun, 3 Jan 2010 11:52:42 +0100
- Subject: Weird behavior of mallocr() function
Hi,
I'm working on some embedded stuff, and for some reason I needed to
get malloc() to work, newlib's release is the 1.18.0.
I've wrote this simple function as stub (newlib is compiled to be reentrant):
caddr_t _sbrk_r (struct _reent *r, int incr)
{
static unsigned char* _heap_current_end = &__heap_start;
if ( &__heap_start + incr > &__heap_end )
{
errno = ENOMEM;
return (caddr_t) -1;
}
unsigned char* _old_heap_end = _heap_current_end;
_heap_current_end += incr;
return (caddr_t) _old_heap_end;
}
The constant addresses are taken from the linker script as above
(these are correct and accessible):
.heap 0x00200a9c 0x404 load address 0x000017b0
0x00200aa0 . = ALIGN (0x20)
*fill* 0x00200a9c 0x4 00
0x00200aa0 __heap_start = .
0x00200ea0 . = (. + 0x400)
*fill* 0x00200aa0 0x400 00
0x00200ea0 . = ALIGN (0x20)
0x00200ea0 __heap_end = .
Anyway malloc() will ALWAYS return a NULL ptr (no matter how much I'm
asking for, could even be 1 byte). This is the debugging output (sorry
about the volume of it):
(gdb) continue
Continuing.
Breakpoint 1, _sbrk_r (r=0x20000c, incr=32) at syscalls.c:16
16 if ( &__heap_start + incr > &__heap_end )
(gdb) step
21 unsigned char* _old_heap_end = _heap_current_end;
(gdb) step
22 _heap_current_end += incr;
(gdb) step
24 return (caddr_t) _old_heap_end;
(gdb) step
25 }
(gdb) step
malloc_extend_top (reent_ptr=0x20000c, bytes=<value optimized out>)
at ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c:2163
2163 ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c: No such file
or directory.
in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2160 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2163 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2146 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2163 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2167 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2169 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2167 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2169 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2178 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2181 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2179 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2181 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2179 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2181 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2185 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2187 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2188 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2194 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2185 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2188 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2194 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
2197 in ../../../../../newlib-1.18.0/newlib/libc/stdlib/mallocr.c
(gdb) step
Breakpoint 1, _sbrk_r (r=0x20000c, incr=1344) at syscalls.c:16
16 if ( &__heap_start + incr > &__heap_end )
(gdb) step
18 errno = ENOMEM;
As you can see, there is a first request for memory, with incr =32,
I've investigated and verified that my function (_sbrk_r()) returns
0x00200aa0 as address, that is the label __heap_start, and so I guess
it's correct.
Anyway mallocr() will make ANOTHER request to _sbrk_r, with incr=1344
(those are bytes, what a huge number).
I've checked the mallocr() source code and afaik this further call to
the function _sbrk_r() has something to do with some disalignement,
but I couldn't figure it out in its entirety.
Could someone with some more experience help me about this?