xPortGetFreeHeapSize() returns wrong values

buffalojump wrote on Thursday, March 18, 2010:

I am using FreeRTOS v6.0.0 and memory module Heap_2.c.

I print the available memory using xPortGetFreeHeapSize(). After using pvPortMalloc() to allocate 48 bytes, then freeing the memory using vPortFree(), my available memory has increased a net gain of 32 bytes?

5944 bytes available from the heap store.
Allocating 48 bytes using pvPortMalloc().
Releasing memory using vPortFree().
5976 bytes available from the heap store.

For a net gain of 32 bytes.

edwards3 wrote on Thursday, March 18, 2010:

This sounds like it needs investigating. Was there not a report to a problem with certain paths through this function recently?

rtel wrote on Thursday, March 18, 2010:

I have tried simply just allocating and freeing blocks, and I always end up where I started.

Could you provide a little more information on how to replicate the problem?  For example, the sequence of events to get into the starting condition, which value 5976 or 5944 is actually correct (if either), etc.  Thanks.

Regards.

yyang2000 wrote on Thursday, March 18, 2010:

Hi,

I wonder where the file is including the xPortGetFreeHeapSize() function. I searched all locations and could not find it in FreeRTOS demo project and source folders.

Thanks,
Bill

sotd wrote on Thursday, March 18, 2010:

Look in heap_2.c

petermeier wrote on Friday, March 19, 2010:

Yes, i’ve reported an error in heap_2.c. 

If there was no need to “split” the block - pxBlock->xBlockSize contains
a wrong value, because it has not been touched/adjusted and contians a value
from a previous call (i guess it comes from xStart.pxNextFreeBlock).

Richard told me to send in some code to prove that issue but i wasn’t able so far to do that - too much work. Hopefully i can perfom this task on sunday evening.

Regards
Peter

buffalojump wrote on Friday, March 19, 2010:

The base heap size (configTOTOAL_HEAP_SIZE = 31K).
portBYTE_ALIGNMENT = 8;
In my environment, I have roughly 20 tasks running.  Most of these tasks will allocate memory using pvPortMalloc(), but not release it. I have one task that performs pvPortMalloc() and vPortFree() with various sizes. In my previous post you see that I have about 5K available from the original 31K. What is strange, this failure is not consistent which make me wonder if its related to how the heap blocks get split, or am I starting to see some effect from fragmentation?

I will try some experiments to see how many times I call pvPortMalloc() and vPortFree() with associated sizes. This might shed some light on the issue.

Note: In my previous post, the value 5944 bytes available from the heap store was before the allocation of 48 bytes. The value 5976 was after I released the memory using vPortFree(). For a net gain of 32 bytes.

petermeier wrote on Thursday, April 08, 2010:

Hi guys,
i’ve added added a sample application to the bug tracker entry. Hopefully that helps to find the error.
I have discovered also another strange error with heap2.c. I’ve build the following code for testing.

UINT8 *ptr;
for(i=1;i<1024;i++)
{
  ptr = pvPortMalloc(i);
  vPortFree(ptr);
}

When iam running in this loop, no other allocations or deallocations are being made, but sadly after i>=300, pvPortMalloc fails. And this is strange, because there can’t be any fragmentation…

Peter

davedoors wrote on Thursday, April 08, 2010:

UINT8 *ptr;
for(i=1;i<1024;i++)
{
ptr = pvPortMalloc(i);
vPortFree(ptr);
}

When iam running in this loop, no other allocations or deallocations are being made, but sadly after i>=300, pvPortMalloc fails. And this is strange, because there can’t be any fragmentation…

Why do you say that. To me it looks like that code does nothing other than fragment the heap.

petermeier wrote on Thursday, April 08, 2010:

Hi dave,
why is the heap being fragmented? I thought fragmentation is something like this:

Alloc a) 100 bytes
Alloc b) 100 bytes
Alloc c) 100 bytes
Alloc d) 100 bytes
Alloc e) 100 bytes

If i free b and d, i have 200 bytes returned but can not allocate 200 bytes at once due to the fragmentation. But i could allocate two times 100 bytes, that would work. Thats fragmentation to me…

What i did was the following:

Alloc a) 1000 bytes (just at startup) - will never be freed.
Alloc b) 500 bytes (just at startup) - will never be freed.
Alloc c) 1 byte
Free c
Alloc c) 2 bytes
Free c

To me, there should not be any fragmentation at all. The returned pointer of c should be always the same. (But i didn’t checked that, in fact).

Probably you can explain to me how heap2.c handles the allocation.

Peter

davedoors wrote on Thursday, April 08, 2010:

I would recommend reading the resources at your disposal, the code, the website http://www.freertos.org/a00111.html and the book.

rtel wrote on Thursday, April 08, 2010:

Having looked at your test code I would suggest you had a couple of fundamental misunderstandings about how the memory allocation works with heap_2.  A couple of pointers:

1) Your tasks have an incorrect prototype.  I’m not sure if this has any effect or not as you are not using the parameter anyway.
2) The loop you use to allocate the memory will definitely result in heavy fragmentation, and you will find that pvPortMalloc() will be returning NULL.  You don’t check for this in your code, so will be passing NULL to vPortFree().  Again I’m not sure what effect this will have exactly, but it won’t be good.

I will wait a few days to see if you can provide a short piece of code that definitely exhibits buggy behaviour - if not I will close the bug report down.

Regards.

petermeier wrote on Thursday, April 08, 2010:

As a result, if heap_2 is working as you described, its not being suitable for using with USB stacks, where i need to allocate memory when inserting a device and free the allocated memory when ejecting the device. So i should use heap_3 instead, right?
The described error is happening when allocating and releasing memory like in a USB scenario: xPortGetFreeHeapSize() is becoming invalid because a higher value is being returned than ever requested. You can see that in the provided heap_2.c and in the log-file.
The incorrect prototype does not effect anything - and it was only for testing and a quick and dirty implementation.
Thanks anyway.

Regards.

rtel wrote on Thursday, April 08, 2010:

I would tend not to dynamically allocate or free anything at run time.  If you do, then always allocate the same size block, and you will not have a problem.  It is unlikely that heap_3 would work with your test code either, but that would depend on the implementation of malloc() and free() that come with your compiler.

Regards.

petermeier wrote on Monday, April 12, 2010:

Hi Richard,
thanks for your reply. Heap_3.c which is using the compiler provided malloc()/free() functions (in my case C32 by Microchip) behaves as expected. If i allocate all needed static memory first and keep an area for the USB stack which needs different block sizes dynamically created and freed there is not a problem. The code, which causes fragments with heap_2.c is now working.

UINT8 *ptr;
for(i=1;i<1024;i++)
{
ptr = pvPortMalloc(i);
vPortFree(ptr);
}

ptr will refer always to the same address, if i not allocate new memory in an other task (of course).

Thanks for your help
Regards