Performant Programming Series: Memory Management (Part 2)
Now that we know how memory is organised in C programs from our last blog.
Let me list few common scenarios that are indicative of poor memory management during coding.
- Invalid Memory Access: This error occurs when a read or write instruction references unallocated or deallocated memory.
- Memory leak: Memory leaks occur when memory is allocated but not released. It would probably not even show up immediately and could take days before cropping up and crashing the program.
- Segmentation Faults: Segfaults are caused by a program trying to read or write an illegal memory location.
- Uninitialized Memory Access: This type of memory error will occur when an uninitialized variable is read in your application.
- Stack overflow exception: The exception that is thrown when the execution stack overflows because it contains too many nested method calls.
The interesting part is that most of these are run time errors and can go unnoticed during compilation. They are also some of the most difficult errors to debug.
Here are a few things you can do to prevent / mitigate memory errors -
- Limit your processes memory using control groups or similar mechanisms, so that one rouge code does not affect other processes running on the system.
- Define what happens when your program crashes due to a OOM(out of memory). For example, you could take a heap dump which can help root cause the memory leak later.
- Do not allocate large variables on the stack. Ensure that any recursive algorithm terminates after a known maximum depth. If a recursive algorithm may recurse an unknown or large number of times, either manage the recursion yourself (by maintaining your own dynamically allocated stack) or transform the recursive algorithm into an equivalent iterative algorithm.
- When space is allocated using the alloc family of functions, the space is allocated permanently until the program terminates, or it is freed. So make sure you free this dynamically allocated memory when you no more need it (mostly within the same scope if possible).
- Use static allocation where possible. Static memory is allocated when variables are declared, compiler knows in advance size of the variable. Also such variables are destroyed automatically when their enclosing function terminates.
So, next time before you raise a pull request go through your code and see if your code is optimized for memory management.
Follow us for more such articles, you can also visit addskill.io to know more about us.