Bonjour Gerome,
through the included macro definition, your first 'free(p)' merely makes 'p' a null pointer. The memory location that 'p' pointed to is not necessarily reclaimed immediately. The garbage collector will free it at its own discretion, unless you force an immediate manual garbage collection by calling 'GC_free(p)'. For most applications, this is overkill. Remember, the point of using a GC is to free yourself from memory management (pun intended )
Your first allocation should and does allocate 16 MB. Your second allocation should allocate 32 MB. This adds up to 48 MB. Most likely, when you allocate the second chunk of 32 MB, the GC has not yet reclaimed the 16 MB that was allocated first, hence your app uses up to 48 MB, plus a little bit of GC overhead.
To show that the GC is not at fault here, please include a timer loop at the end, or whatever that keeps the app alive for some more time. If you have tools to look at memory allocations while the app remains alive, you'll notice that eventually both memory block allocations will be reclaimed by the GC.
If you use free(p) when using my macro definitions, you're not actually freeing up anything at that moment. You're just telling the GC that it's save to reclaim the objects that your pointers pointed to. Unless you force the GC to do its thing immediate, the GC decides when it actually performs a garbage collection.
Hope this helps.
Hans