[En-Nut-Discussion] NutHeapAlloc Error?
Timothy M. De Baillie
debaillie at ciholas.com
Tue Oct 14 21:30:13 CEST 2008
Timothy M. De Baillie wrote:
> Nathan Moore wrote:
>
>> On Mon, Oct 13, 2008 at 3:06 PM, Timothy M. De Baillie <
>> debaillie at ciholas.com> wrote:
>>
>>
>>
>>> I'm trying to trace down a bug on a system that has REALLY low memory
>>> and has lots and lots of mallocs. So this may not really be a problem,
>>> but I thought I would see what others thought.
>>>
>>> in the OS, os/heap.c,
>>>
>>> ~~~ OS CUT ~~~
>>> void *NutHeapAlloc(size_t size)
>>> {
>>>
>>> ......
>>>
>>> if (size >= available) {
>>> #ifdef NUTDEBUG
>>> if (__heap_trf)
>>> fputs("MEMOVR\n", __heap_trs);
>>> #endif
>>> return 0;
>>> }
>>>
>>> /*
>>> * We need additional space in front of the allocated memory
>>> * block to store its size. If this is still less than the
>>> * space required by a free node, increase it.
>>> */
>>> if ((size += MEMOVHD) < sizeof(HEAPNODE))
>>> size = sizeof(HEAPNODE);
>>> ~~~ OS CUT ~~~
>>>
>>> Should the check "if(size >= available)" not happen after the last two
>>> lines?
>>>
>>> From what I read, if you request 11 bytes and had exactly 11 bytes
>>> available, then you would cause a memory wrap of some sort.
>>>
>>>
>>>
>> I think it would result in similar behavior as if you had 100 bytes free in
>> 10 byte chunks and requested 20 bytes.
>> You'd check each of the chunks, none of them would be big enough, and in the
>> end (when (0== (node = node->next))
>> you'd break out of the loop.
>> It would behave correctly, as far as I can tell, but since the available
>> test is done anyway it might as well be done after
>> the size adjustments.
>>
>> Nathan
>> _______________________________________________
>> http://lists.egnite.de/mailman/listinfo/en-nut-discussion
>>
>>
>>
> Ok, so we made this change and we are still having malloc issues.
> However, we have traced it down to one specific line in os/heap.c:
>
> *fpp = fit->hn_next;
>
> in the else of:
>
> if (fit->hn_size > size + sizeof(HEAPNODE) + ALLOC_THRESHOLD) {
>
> The system "locks up" or jumps to abort if you attempt to set *fpp to
> NULL. So this happens if your "fit" is the last heap in the heap list
> and you can't split it. I don't understand how setting a pointer to NULL
> causes the ARM to abort, but it does.
>
> Why would setting *fpp to NULL cause a lockup and how do we resolve this
> bug?
>
> Thanks in advanced,
>
> Tim
>
> _______________________________________________
> http://lists.egnite.de/mailman/listinfo/en-nut-discussion
>
>
OK, this is 100% repeatable. If the "fit" heap is chosen and is the last
heap section, it WILL fail on this instruction. Here is some code that
WILL exercise this.
~~~begin code~~~
FILE *uart;
unsigned long uart_baud = 115200;
void main(){
//initialize your uart to allow to see if things are still working when
we complete
NutRegisterDevice(&DEV_UART, 0, 0);
uart = fopen(DEV_UART_NAME, "r+");
_ioctl(_fileno(uart), UART_SETSPEED, &uart_baud);
outr(AIC_SMR(US0_ID), 0x04);
fputs("\r\nWelcome to the test.", uart);
NutSleep(3000); //allow serial to go out
fputs("\r\nHere goes the test\r\n.", uart);
NutSleep(30); //allow serial to go out
//malloc all but a one less than the amount needed to split
malloc(NutHeapAvailable()-sizeof(HEAPNODE)-ALLOC_THRESHOLD+1); //this
will malloc all the space except just enough to NOT split the left over
space
//now report if we are working
fputs("\r\nIt didn't fail!!\r\n", uart);
for(;;){
NutSleep(1000);
}
}
~~~end code~~~
More information about the En-Nut-Discussion
mailing list