This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: Strange malloc() problem, what am I missing
- From: Per-Henrik Lundblom <ph at whatever dot nu>
- To: newlib at sourceware dot org
- Date: Mon, 21 Aug 2006 11:19:00 +0200
- Subject: Re: Strange malloc() problem, what am I missing
- References: <20060810074954.GA22631@whatever.nu>
* Per-Henrik Lundblom <ph@whatever.nu> [060810 09:50]:
> Hi,
>
> I'm using newlib in a project involving FreeRTOS running on an ARM7
> target (Philips LPC2138, 32kb RAM). I have use pre-compiled GnuARM
> toolchain available from www.gnuarm.net running on both Windows and
> Linux. The newlib version is 1.14.0.
>
> I have spent the last week trying to sort out a strange problem that
> occurs when using malloc() (eg. malloc_r()). In my application I alloc a
> few "large" blocks (~1kb) and then continously alloc and free a lot of
> small chunks (8-100bytes). I haven't fully understood exactly how the
> malloc implementation in newlib works but I will try to describe the
> problem:
>
> Eventually a 24 bytes allocated chunk will be free:d and placed in the
> 24 bytes bin. This is the only chunk in the 24 bytes bin so the two
> next/prev chunk pointers in the chunk points to the same location and
> that location is the chunk itself.
>
> This chunk eventually is allocated with a malloc(18) which turns out to
> a request to a 24 bytes chunk. The code executed is mallocr.c:2357.
> victim and q is set and are not equal so the code block starting at line
> 2374 is executed. The unlink() macro is executed. Here I experience the
> strange problem. Unlink doesn't release the chunk from the 24 byte bin
> in the __malloc_av_ (av_ in mallocr.c). Because the chunk is the only
> chunk in the 24 byte bin I get the impression it should!
>
> Anyway, the chunk is allocated and returned to the application that
> writes data to it. The next/prev pointers that where in the "head" of
> the chunk when it was free is of course overwritten because this memory
> is allocated and returned to the application.
>
> After a while a malloc(8) is requested. This is again seen as a small
> request by malloc. The code in the block mallocr.c:2357 is executed. q and
> victim is set, but because these are equal, the q and victim is advanced
> one bin. But now this bin is still pointing at the chunk that where
> allocated to the application previously! The application has overwritten
> the next/prev pointers in the chunk and because of this, these pointers
> are invalid and results in a data abort on the ARM7 when executing the
> unlink() macro.
>
> I have fixed this with a simple if statement checking if all the
> conditions mentioned above is true. If yes, the __malloc_av_ bin array
> is updated. See patch below.
>
> THE REAL QUESTION IS: What am I missing, have I mis-configured
> something? I can't really see such a simple thing beeing a flaw in the
> implementation.
>
> --- newlib-1.14.0/newlib/libc/stdlib/mallocr.c 2005-10-07 20:07:26.000000000 +0200
> +++ newlib-1.14.0_patched/newlib/libc/stdlib/mallocr.c 2006-08-09 17:07:14.4230 64700 +0200
> @@ -2367,6 +2367,7 @@ Void_t* mALLOc(RARG bytes) RDECL size_t
> if (victim == q)
> {
> q = next_bin(q);
> + victim = (mchunkptr) q;
> victim = last(q);
> }
> #endif
> @@ -2374,6 +2375,11 @@ Void_t* mALLOc(RARG bytes) RDECL size_t
> {
> victim_size = chunksize(victim);
> unlink(victim, bck, fwd);
> +if (victim->fd == victim->bk && last(q) == first(q) && victim->fd ==
> last(q))
> +{
> + q->fd = q;
> + q->bk = q;
> +}
> set_inuse_bit_at_offset(victim, victim_size);
> check_malloced_chunk(victim, nb);
> MALLOC_UNLOCK;
>
Doesn't anyone have a clue about this?
/PH
--
Per-Henrik Lundblom epost: ph@whatever.nu
telefon: 0733-20 71 26 hemsida: www.whatever.nu