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
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).