Question

We are using the uC/OS-III RTOS of Micrium. We are trying to the return value of malloc on the RTOS. When we do a malloc of 99999 (too much for the RAM) before the RTOS is started, we get a null pointer back, which is what we expect.

When we do this same malloc when the RTOS is started and in a task, we do not get a null pointer back, which we do not expect. The system does freeze at this moment though.

Does anyone have an explanation for this?

Thanks in advance

Edit:

For the info: we are using a RX62N micro controller of Renesas and the GNURX compiler

The program does not actually freeze. The program 'thinks' it gets a useful pointer (not a NULL pointer), and continues running. On a certain point the program changes its Program Counter to 00000000 and stops. So it does not get in a Exception, and therefore we can not catch it.

However there is something different when the malloc is called before the RTOS starts and when the RTOS is started. The difference is in the really deep assembly code of malloc.

On a certain point the following instructions are executed

CMP         R1,R7
BGTU.B      0FFF802C0H
ADD         R14,R7

When we are trying to allocate too much RAM the BGTU.B instruction should not branch and the program then continues with the ADD instruction. This works perfectly when malloc is executed before starting the RTOS and fails when we do it afterwards.

These are the values I get in several cases

Outside RTOS (allocable number: 10)
R1: 00008348
R7: 00000014

Outside RTOS (not allocable number: 9999)
R1: 00008348
R7: 00002718

Inside RTOS (allocable number: 10)
R1: FFFFF9D0
R7: 00000014

Inside RTOS (not allocable number: 9999)
R1: FFFFF9D0
R7: 00002718

I hope the whole situation is clear, I tried to explain it as good as I can :P

Thanks in advance

Was it helpful?

Solution

In all but the second case in the illustration case R7 appears to contain the size of the allocation (requested size + alignment + heap management data). Intuitively R7=0x2718 would correspond to an allocation of 999 bytes so I suspect that this might be a typo.

R1 I would guess contains the size of the heap block the memory will be allocated in, since then the CMP would make sense. If the block is not large enough, it will fail.

However when the RTOS is running, the value in R1 becomes very large, and is obviously not correct. This could happen if your heap became corrupted. This will happen if you overrun a buffer allocated on the heap. If you are allocating thread stacks from the heap, and a stack is too small, that would have the same effect. Your thread stacks must be large enough for the worst-case call stack, plus whatever is required by the RTOS to support a context switch. Even if you are not allocating stacks from the heap, if a thread stack is adjacent to the heap memory, a stack overflow could have the same effect.

Another way the heap may be corrupted is by concurrently performing allocation or deallocation in more than one thread without enforcing mutual exclusion or a critical section. It is unlikely that the standard library heap management is thread-safe unless you have made the necessary modifications to integrate it with your RTOS - this may be the case if the RTOS and standard library are from the same vendor (for example if both were supplied with the compiler).

OTHER TIPS

We are finding that malloc works fine when called before the UCOS-III OS is started. When called from a thread it fails and return a NULL pointer. I suspect this is due to a check against the stack which is of course not valid when running in a thread which can have an arbitrarily placed stack. I can see in the map file that the library is referring to an specific sbrk (lib_a-sbrk.o)function and I cant find any source for that function. It is commonly known that the default GNU sbrk function will check against the current stack pointer to see if the current break is beyond the SP and fail.

Unfortunately we have to rely on malloc as we are using a complex C++ library, as we have megabytes of memory we are not concerned about fragmentation, we just want malloc to work. We are actually not even concerned about re-entrancy as we are only using malloc in a single thread.

Would it be possible to shed some light on how the heap functions are implemented in libraries. We are using the ARM-9 chip.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top