Scope
This is Part 2 of a white paper intended to provide a brief overview of lessons learned in creating robust systems over the past 35 years of embedded systems development (starting with the Intel 4040). This part will address Memory Leaks; what they are; how they are created; how to detect them and how to prevent them.
Memory Leaks
A memory leak is defined as “A bug in a program that prevents it from freeing up memory that it no longer needs. As a result, the program grabs more and more memory until it finally crashes because there is no more memory left.”[1] See https://en.wikipedia.org/wiki/Memory_leak for a good summary of memory leaks.
A Simple Example (in C)
char * foo(char *bar,unsigned int size) { char *ptr = malloc(1000); *ptr = 0; strncat(ptr,bar,size); StripSpaces(ptr); *bar = 0; strncat(bar,ptr,strlen(ptr)); Return bar; }
The memory assigned to ptr can never be accessed and every time foo gets called a 1000 byte memory leak will occur.
… they can go undetected and cause no harm even after days of testing or operation.
What problems do Memory Leaks create?
One of the major problems with memory leaks is that they can go undetected and cause no harm even after days of testing or operation. Then one day, the system will fail to be able to allocate the necessary memory it needs to operate and the system will crash (hopefully if our other guidelines are followed, the system will restart).
For a system to be robust there must be zero memory leaks after hours of operation. Imagine that your embedded system runs 24/7 and there is function performed every hour. If that function allocates 1k bytes of data and does not free that memory, it will eat 8 meg after one year of operation. With some systems that have tons of memory, your embedded application could have passed thousands of hours of testing and the memory leak go undetected.
How can we prevent Memory Leaks?
Some experts dodge the issue with statements like follows:
Programs must avoid dynamic data allocation, and avoid the use of (built-in) library functions that make use of dynamic memory allocation (e.g. string.h).[2]
Avoid using string.h? Avoid using dynamic data allocation? This advice may work for military and aerospace embedded systems but is totally impractical for industrial and commercial embedded systems. Even relatively simple user interfaces now use GUI’s that use massive amounts of dynamic data allocation.
There are three (simple to state – but difficult to implement) principles that we follow:
- Thorough educate all designers about how to design for zero memory leaks. The principle is simple but it must be hammered into the minds of every designer and programmer. In the famous words of Admiral Hyman Rickover “Good ideas are not adopted automatically. They must be driven into practice with courageous impatience.”
- Independently code review all designs – Memory leaks are often easier to detect during code review than during test.
- Utilize memory leak detection software during all phases of test. It is far easier to start using these tools early in development rather than trying to add them on when a leak is detected the hard way. With Visual Studio programming, you can use “crtdbg.h” and CRTDBG_MAP_ALLOC. For Linux (non-kernel programming) Eclipse provides some tools for detecting memory leaks. memwatch is a mature and open source tool. (https://www.icewalkers.com/Linux/Software/52790/memwatch.html ) MemoryScape from TotalView provides another tool.
Under Linux, using command line tools like “top” are inadequate but can be used to watch for large leaks. Get a set of good tools learn how to use them – and then (Duh!) use them. Believe me – I know that in the rush of development, this can get missed.
I’m Programming Java – Do I need to worry about Memory Leaks?
From the IBM web site:
If the term Java™ memory leak seems like a misnomer to you, rest assured that you are not alone; after all, you were promised that Garbage Collection (GC) in Java will relieve you from the mundane duties of allocating, tracking, and freeing the heap memory. Indeed, the promise has been delivered, so it is reasonable — and to quite an extent correct — for you to conclude that there will be no memory leaks in your Java program. However, the catch is that GC can take care of only typical heap management problems.[3]
The above referenced IBM article has an excellent example of how you can create memory leaks with Java. If you are programming in Java it is well worth your time to fully understand how you can do this so that you can avoid it.
But we all are expert Java programmers and never create memory leaks this way with Java! But alas! We are still not out of the woods. We have found memory leaks in the Java implementations (from unmentioned suppliers). They can only be found with massive amounts of testing and measuring. Basically we noticed that by running the same sequence over and over we could exhaust 100 meg of RAM in 24 hours. And starting the Java thread with the command switch to limit dynamic memory usage did not stop the leak because the leak was in the JVM. When all was said in done, over 30 memory leaks were detected in the JVM.
The moral of the story is to test, re-test and test some more – all the while watching for memory leaks. Of course you won’t find the leaks in your Java program but in the JVM.
[1] https://www.webopedia.com/TERM/M/memory_leak.html
[2] Development Guidelines for Dependable Real-Time Embedded Systems by Michael Short