This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Strange malloc() problem, what am I missing


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;

/PH

--
Per-Henrik Lundblom           epost: ph@whatever.nu
telefon: 0733-20 71 26        hemsida: www.whatever.nu


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]