lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] How to release all memory to track leaks


From: Erik Ekman
Subject: Re: [lwip-users] How to release all memory to track leaks
Date: Wed, 9 Jun 2021 19:53:26 +0200

The lwIP unit tests use this code to verify that all memory has been returned:
https://git.savannah.nongnu.org/cgit/lwip.git/tree/test/unit/lwip_unittests.c#n48

On Fri, 4 Jun 2021 at 14:30, Dave Nadler <drn@nadler.com> wrote:
>
> R. Diez - While you are doing bare metal, you can find more info about newlib 
> memory use here:
> https://nadler.com/embedded/NXP_newlibAndFreeRTOS.html
> Hope that helps,
> Best Regards, Dave
>
> On 6/4/2021 7:43 AM, Trampas Stern wrote:
>
> In C there is a _sbrk(int incr) function.  This function is called when 
> memory allocation or deallocation happens.
> The newlib has their own version of this function, however via linker with 
> the --specs=nosys.spec you can disable the default version and add your own.
>
> You can google sbrk for more information.....
>
> What I do is implement a break point in the function to see who is allocating 
> memory. I also keep track of the memory allocation as the program runs.
>
> What I have found is that newlib memory allocation does not always free 
> memory and it also allocates memory if you are using floating point printf(). 
>  What happens is newlib has it's own internal memory management system.  For 
> example if you malloc(4) newlib might actually request a block of more than 4 
> bytes then when you free those 4 bytes newlib might not actually release 
> those bytes and instead mark the block as free internally and reuse it for 
> another malloc().
>
> What I do in my programs is implement a serial port command line interface 
> using a debug uart. Then I have a memory command where I print out the stack 
> and heap usage. I can also monitor the stack and heap usage as my program 
> runs to help handle stack and heap overflow more gracefully if needed. I 
> track maximum heap used as well as current heap usage.
>
> I have found that libraries like newlib standard C library will often malloc 
> memory.  This is highly dependent on the functions you use. For example if I 
> recall correctly when you enabled floating point on newlib it will allocate 
> memory when you do a floating point printf().  To avoid this and issues with 
> reentrant on printf()/sprintf() I just implemented my own version.  Every 
> line of code in the project becomes your problem, even standard C library 
> calls.
>
> As far as releasing all memory for lwip, I find this to be not needed. The 
> most important thing is to know what memory is being used and that it is not 
> growing. For example in C you could do this:
>
> uint8_t data[512];
> void main(){}
>
> This creates room in RAM for 512 bytes of data that is never released.  
> However this does the same thing:
>
> uint8_t *data;
> void main(){
> data=malloc(512);
> }
>
> That is both programs now need 512 bytes of RAM which is never released, the 
> only difference is one is in heap while the other is in the static allocation 
> (bss) section of RAM.   Hence malloc is not evil as many people have said, 
> rather it is a tool you have to know how to use correctly.
> I will say that 99% of the time the code I see that uses malloc() is evil, so 
> there exists a strong correlation to bad code and malloc, but it is not 
> memory allocation's (malloc) fault.  It is always the programmer not 
> understanding what they are doing in the code.
>
> Note I monitor stack and heap usage, not just for my code, but also for the 
> next guy.  For example projects live long after I am gone, so if the next 
> programmer inserts code that overflows stack or heap it is good that the 
> monitoring catches the error and lets them know before they release code to 
> production, i.e. defensive coding techniques.
>
> My sbrk function is below, but depends on the linker variables __HeapBase, 
> and __HeapLimit to work.  Note I often add a macro,  HALT_IF_DEBUGGING(), 
> which will insert a breakpoint into the code when a debugger is attached to 
> help track down which functions are doing memory allocations.
>
> Thanks
> Trampas
>
>
> extern uint32_t __HeapBase;
> extern uint32_t __HeapLimit;
> uint32_t getHeapUsed(void);
> uint32_t getHeapSize(void);
> int32_t getLastMalloc(void);
>
> uint32_t heapUsed=0;
> int32_t lastMalloc=0;
> uint32_t getHeapUsed(void)
> {
> return heapUsed;
> }
>
> uint32_t getHeapSize(void)
> {
> return (uint32_t)&__HeapLimit-(uint32_t)&__HeapBase;
> }
>
> int32_t getLastMalloc(void)
> {
> return lastMalloc;
>
> }
>
>
> static unsigned char *heap = (unsigned char *)&__HeapBase;
> static unsigned char *max_heap = (unsigned char *)&__HeapBase;
>
> uint32_t getMaxHeapUsed(void)
> {
> if (max_heap == NULL)
> {
> return 0;
> }
> return (uint32_t)max_heap - (uint32_t)&__HeapBase;
> }
>
> uint8_t *getHeapPointer(void)
> {
>
> return heap;
> }
> extern caddr_t _sbrk(int incr)
> {
>
> unsigned char *prev_heap;
>
> prev_heap = heap;
>
> heap += incr;
>
> if (heap > max_heap)
> {
> max_heap=heap;
> }
> lastMalloc = incr;
> heapUsed = (uint32_t) heap - (uint32_t) ((unsigned char *) &__HeapBase);
>
> //HALT_IF_DEBUGGING();//if you hit this something allocated memory, which 
> maybe you do not want...
>
> //for (;;) { }
>
> return (caddr_t) prev_heap;
> }
>
> On Fri, Jun 4, 2021 at 6:14 AM R. Diez via lwip-users <lwip-users@nongnu.org> 
> wrote:
>>
>> Hi all:
>>
>> I have a bare-metal (Newlib, no threads) firmware that uses lwIP and its 
>> httpd server to provide a simple web interface.
>>
>> The firmware is actually quite complex in other areas. I am trying to 
>> identify and track down memory leaks, so I implemented a "shutdown" command 
>> in the debug console that releases all resources and checks the remaining 
>> allocated bytes with mallinfo().
>>
>> I suspect some of the remaining memory "leaks" belong to lwIP and/or its 
>> httpd server, because they only come up after having downloaded the web page 
>> once. They are probably not real leaks, because memory usage does not grow 
>> over time.
>>
>> It is hard to say, because I have not figured out yet how to track memory 
>> allocations in an embedded Newlib firmware like this.
>>
>> In any case, I would like lwIP to release all memory on shutdown, in order 
>> to locate any memory leaks in other parts. The trouble is, there are 
>> routines like lwip_init() and httpd_init(), but no xxx_terminate() 
>> counterparts.
>>
>> I tried removing all interfaces with netif_remove(), but that is probably 
>> not enough.
>>
>> Is there some trick I could use? For example, something like ticking all 
>> state machines again after all interfaces have been removed could possibly 
>> trigger a complete memory release all over the place.
>>
>> Thanks in advance,
>>   rdiez
>>
>> _______________________________________________
>> lwip-users mailing list
>> lwip-users@nongnu.org
>> https://lists.nongnu.org/mailman/listinfo/lwip-users
>
>
> _______________________________________________
> lwip-users mailing list
> lwip-users@nongnu.org
> https://lists.nongnu.org/mailman/listinfo/lwip-users
>
>
> --
> Dave Nadler, USA East Coast voice (978) 263-0097, drn@nadler.com, Skype
>  Dave.Nadler1
>
> _______________________________________________
> lwip-users mailing list
> lwip-users@nongnu.org
> https://lists.nongnu.org/mailman/listinfo/lwip-users



reply via email to

[Prev in Thread] Current Thread [Next in Thread]