Values in heap4 space

TM4C1290NCPDT application has 3 RTOS tasks (1500 bytes each) and uses heap4.

There is a buffer (pointer to unsigned int) whose memory is allotted using pvPortMalloc and freed. Even prior to any memory allocation, there are non-zero values written into the heap 4 space. This is causing garbled characters to show up when the application prints small font.

This happens soon after initialization. The USB interface sends a command to initialize the hardware.

m_ucUsbInputBufferTemp = (UINT8*)pvPortMalloc(ucNumMsgs*MAX_USB_MESSAGE_SIZE);

When this memory is allotted, the random bytes show up. This buffer is freed. The same start address is assigned to the buffer of interest. The non-zero values of bytes following this address are still there. What can I do to make this go away? The application size if only 207 kB, MCU has 1MB flash.

Thanks,
Priya

What isn’t clear from your question is what you mean with the buffer being allocated and then freed and then start address assigned to buffer of interest.

I suspect that your problem is a pointer manipulation issue and without access to your code we’ll all struggle to help you further than that.

There is nothing in the kernel that will clear the heap space to any value prior to it being used, but if you are using heap_4 in its default configuration then the heap_4 is basically a statically allocated buffer that your compiler should place in the bss segment, and then your start up code should clear the bss section to zero. If that is not happening then it would point to a problem with your C startup code.

Your post does not give any indication as to why that is related to the first problem.

m_ucUsbInputBufferTemp = (UINT8*)pvPortMalloc(ucNumMsgs*MAX_USB_MESSAGE_SIZE);
vPortFree(m_ucUsbInputBufferTemp);

m_ucArcnetInputBuffer = (UINT8*)pvPortMalloc(ucNumMsgs*MAX_USB_MESSAGE_SIZE);
is assigned the same start address of 0x20004B30.
vPortFree(m_ucArcnetInputBuffer);

The garbled characters are circled in red.

At startup all of heap 4 space is 0

.bss 0 2000026c 00014e1c UNINITIALIZED
2000026c 00009c40 heap_4.obj (.bss:ucHeap)
20009eac 00004b00 Printhead_Interface.obj (.bss:m_ucBitmapPrintBuffer)
2000e9ac 00002008 (.common:REPMarc_RcvQue)
200109b4 00002008 (.common:REPMarc_SndQue)
200129bc 00000800 (.common:REPMarc_NowSndData)
200131bc 00000800 (.common:REPMsrv_IBWpkt)

Memory given by the allocations functions are NOT promised to be filled with zeros, so if you get a block that had been previously used, you may see old data in it. If you want zeroed memory, you need to clear it yourself (or use a function that does clear the memory)

You can also get random bytes if you program writes through bad pointes, in which case maybe you are just (un)lucky enough that it isn’t hitting something that valuable so you are only getting mild garbling.

When pcPortMalloc is called, memory is allocated 4 bytes at a time. Though the max USB data size is 64 bytes. Why is this? The non-zero chars are some where within this 64 byte space.

What function can be used to clear memory? I am unable to use memcpy because I want to clear memory past the 4 bytes that were allotted.

Thanks
Priya

pvPortMalloc will allocate the number of bytes requested, rounded up to the alignment value, plus it adds a header before the return block to provide information for pvPortFree(). I don’t know why you say it allocates 4 bytes at a time, it typically allocates in units of 4 bytes on many processors, but one allocation can use many units.

I would use memset to clear the memory, and it can clear as much of the buffer as you allocated.

When you allocate the memory, it’s yours, and you can clear it if you want (using memset(), for example) and then use it as your USB buffer.

But if you free it, it’s no longer yours, and the system can do what it likes with it, including allocating it to someone else or writing (what from your point of view is) garbage all over it. And, if you write to it, you’re trampling over some other part of your program’s memory.

Once you’ve allocated it, hang on to it.

BlockquoteAnd, if you write to it, you’re trampling over some other part of your program’s memory.

Blockquote
Yes, using memset simply moves the non-zero data to a different memory location.
I used the allocated memory after copying from the USB buffer, cleared it using memset then freed it. This makes the garbled chars go away.

I could not find any other memory leak.

Thanks,
Priya

Unless you are needing security for things like cryptography, where the contents of the buffer might be valuable information you don’t want to leak, there is no need to clear the buffer before freeing it, as the memory allocation routines might use pieces of it for administration, so that won’t guarantee that the allocated buffer is all zeros, if you need it all zeros, clear it just after allocating. (You might make it so that it is likely all zeros, but in one sense that makes problems tougher to find as they will only occasionally show up).

I am getting confused by this thread (especially the bits about a memory leak) and would like to restate what we think the issues are as a numbered list so can address each. Here is what I think we are discussing,:

  1. When malloc (or pvPortMalloc()) is called the first time the allocated buffer is cleared to zero, but the second time it is not.

As already mentioned, the standard c library malloc() does not clear allocated memory to zero, if it did it would not be complying with the standard. Also as already mentioned, if you use heap_4 then the heap memory space is a statically allocated array which, also in accordance with the C standard, does get cleared to zero by the C start up code at initialisation time (i.e. before your program executes) . Therefore the first allocation is cleared to zero not because pvPortMalloc() cleared it to zero, but because it was cleared to zero before your application ever executed. All calls to pvPortMalloc() return a buffer that contains whatever the buffer contained before pvPortMalloc() was called.

  1. How to clear memory to zero.

The standard C library to clear memory to zero is memset(). This is part of C language fundamentals that need to be understood before writing applications in C.

  1. The contents of memory seems to change between calls to malloc/pvPortMalloc.

If you use the following sequence:

x = pvPortMalloc( 1000 );
vPortFree( x );
y = pvPortMalloc( 1000 );
vPortFree( y );

and it just so happens that x == y (i.e. they point to the same buffer) then the values contained in the buffer pointed to by x and y would normally be expected to be the same because nothing else in that sequence wrote to the buffer pointed to by x/y.

Are you claiming the memory changes even though nothing else is writing to it?

If so, then it is possible in a multithreading system that another task executed and wrote to the memory. Or that your code has a bug and a peripheral interrupt service routine, or DMA, or other peripheral function wrote to the memory.

I don’t understand this point, but when you call malloc()/pvPortMalloc() you receive a buffer that is at least as big as requested using the parameter to the malloc/pvportmalloc call. pvPortMalloc() is a really simple function, so if you step into it you will see that, like all malloc() implementations that follow the C standard, it will align the start address to be correct for the processor, it will allocate a little memory for metadata that enables it to free the memory again, and it will also effectively align the end address to be correct for the processor - so internally and unseen from the application it will actually allocate more than you asked for. On a processor that has 32-bit access requirements it will always align to 4 byte addresses otherwise your the processor will generate an exception with certain types of access.

Any other points in this thread?

If replying, please use the number in the above so I know which part we are talking about…and as per my previous comment understanding the fundamentals of how the language works is really a precondition of writing a USB driver.

1 Like