This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCSv6 malloc falls into infinite loop

Expert 1140 points


Hi,

Some part of code  (don't know yet which one) where I do lots of small mallocs and frees causes the problem to next malloc call where I need to allocate 1000 bytes of memory. I started to debug this code and saw something interesting:

function void *malloc(size_t size) in memory.c

void *malloc(size_t size)
{
    memsz_t allocsize = size;
    PACKET *current, *next, *prev;

    if (allocsize == 0) return 0;

    if (allocsize < MINSIZE) allocsize = MINSIZE;

    /*-----------------------------------------------------------------------*/
    /* We may need to adjust the size of the allocation request to ensure    */
    /* that the address of the field "next_free" remains strictly aligned    */
    /* in all packets on the free list.					     */
    /*-----------------------------------------------------------------------*/
    if ((allocsize ^ OVERHEAD) & 1) ++allocsize;

    _lock();

    if (first_call) minit();

    current = sys_free;
    prev = 0;

    /*-----------------------------------------------------------------------*/
    /* Find the first block large enough to hold the requested allocation    */
    /*-----------------------------------------------------------------------*/
    while (current != LIMIT && -current->packet_size < allocsize)
    {
	prev = current;
	current = current->next_free;
    }
...
}

The program gets stuck in this while loop because the condition 

-current->packet_size < allocsize

is always true (current->packet_size = 1022, allocsize = 1000). With the minus sign it is -1022 and subsequent assignments of current = current->next_free never change this situation because every next_free is 1022.

When calling malloc before this faulty part of my code occurs and when mallocs return correctly I can see the packet_sizes of current and next_free to be negative values, so the minus in the comparison is understood.

Have anyone saw something similar and know what might cause such problem? There are no memory leaks in my code program, that is for sure :-) 

EDIT: ok, found it. It was double freeing memory pointed by the same pointer. As to whatt happens then this has been covered in: http://stackoverflow.com/questions/135474/what-happens-when-you-try-to-free-already-freed-memory-in-c

You will be able to see the problem on this simple example:

#include <msp430.h> 
#include <stdlib.h>

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;

    char* buf;

    buf = malloc(100);
    free(buf);
    free(buf);
    buf = malloc(50);

	return 0;
}

When compiled with CCSv6 at default settings the program will never reach return 0, it will instead get stuck inside buf = malloc(50).

Regards,

tml

  • tml said:
    while (current != LIMIT && -current->packet_size < allocsize)

    YPou should use brackets. It's easy to make an operator precedence error (even though it doesn't seem to be the case here).

    tml said:
    It was double freeing memory pointed by the same pointer.

    Well, that's bad.
    Usually, malloc stores organizational data right before the allocated memory. This data is chained (pointing to the next data block). This way, malloc can go through the chain and find the first free memory block that is large enough for the request.

    If you malloc a memory block, right before it, info is stored about the size of the block. And right after it, the next info is expected, containing data about the following ram (used/free, size). If you free a memory block, the data is updated and subsequent free blocks are joined together. If you free a block a second time, this is attempted again, even though the data chain does maybe not contain this info block anymore. So the chain may become corrupted to the attempt to free the memory block may corrupt the next memory block in use or even lead to an endless recursion.

    Well, using malloc/free a lot of times with different sizes is a bad idea on a system with limited resources. malloc is prone to heap fragmentation. Worst case, you'll at some time get a pattern of used and unused memory blocks where in total half of the heap may still be free, but none of the free small blocks is large enough to fulfill your malloc request, returning a null pointer.

**Attention** This is a public forum