A memory leak regards the concept of "non released and unused memory, an unintentional failure that makes your program hold memory when is not longer needed". This means that even you create a new instance of an object — in C++ — without releasing it’s memory; you request a memory block — in C — with malloc(3), mmap(2) or sbrk(2) families of functions and similar tasks; or simply you setup an object reference without releasing the reference, when you left the object usage in your code logic and the reference is kept without letting the interpreter or garbage collector destroy it — as in dynamic and virtual machine based languages.
A memory leak is the gradual loss of available computer memory when a program (an application or part of the operating system) repeatedly fails to return memory that it has obtained for temporary use. As a result, the available memory for that application or that part of the operating system becomes exhausted and the program can no longer function. For a program that is frequently opened or called or that runs continuously, even a very small memory leak can eventually cause the program or the system to terminate. A memory leak is the result of a program bug.
Source: WhatIs.com
From the basics, we will review single tasks on C, to more complex tasks on dynamic languages, such as JavaScript. My apologies to all those people that thinks that "memory does not matter" and saw you "don’t worry about memory if you are using a language with a garbage collector" and even saw you " don’t worry about memory if you are using a dynamic language", but certainly all those people are wrong. Releasing memory and kind resources is an important task. Just take a look on the Internet and search about System.OutOfMemoryException for C#, java.lang.OutOfMemoryException for Java, "PHP Fatal error: Allowed memory size of NNNNNNN bytes exhausted" for PHP, and some other well known issues. Isn’t strange that you will find some of those errors currently running on Web Servers. Usually it have a common, quick and dirty solution: "just increase the memory limit, stack size or the amount of memory available for your program".
the basics with c
On C, every reserved block must be released. The standard library way to allocate memory is the malloc(3) family of functions. Also, there are many programs and languages too which are using it’s own memory allocator through system calls such as mmap(2) and sbrk(2). If you are using an Open Source operating system, such as Linux or FreeBSD, you can take a look on your system wide memory allocator implementation. Dynamic allocations, given by this kind of calls, allocate memory on the heap, which can grow until it reaches the memory limit given by the system that are running on.
A single way to track the memory used by your program can have the form of the next piece of code:
#ifdef CUSTOM_MEMORY_TRACK #define malloc(s) my_malloc(s); #define free(p) my_free(p); #endif /* !CUSTOM_MEMORY_TRACK */ int total_allocation_calls = 0; void *my_malloc(size_t sz) { total_allocation_calls++; return malloc(sz); } void *my_free(void *p) { total_allocation_calls--; free(p); } /* to use with as: atexit(my_display_allocations); in main() */ void my_display_allocations (void) { printf("Total Allocations: %dn", total_allocation_calls); }
Then, if you use this piece of code and setup an atexit(3) call in main, you can get a message like: "Total Allocations: 0", only if your program does not have memory leaks. And "Total Allocations: n", with n greater or equal to one, if your program have memory leaks. Be careful with that! There are many functions or systems calls that are allocating memory!, in example the strdup(3) family of functions, and those functions requires that the allocated memory must be released (deallocated) after they are used. For C programmers, it’s known that there are a lot of nice tools to detect memory errors, such as memory leaks and invalid memory access (write/read). Surely you know about valgrind! :D. Do you understand the valgrind output?.
First of all, change your mind, resolve compile time errors. Try compiling your programs with -Wall -Wextra -Wshadow -pedantic -std=c99 flags. They will show you how portable is your code. Let’s go with valgrind now, where the error format have the form: "Error Messagen…backtrace…"
Address 0×0000000 is n bytes inside a block of size m free’d
==28023== Address 0x42d4010 is 8 bytes inside a block of size 100 free'd ==28023== at 0x40270FC: realloc (vg_replace_malloc.c:429)
The given address have an incomplete memory release operation, where it holds n bytes of m free’d and occurs at memory address 0x40270FC, in the function realloc(3) on the file vg_replace_malloc.c at line 429. Since it is a system wide function and it is not a part of your program, usually the system do no have a bug, and you must look on the entire backtrace until you reach your code in the backtrace. When you don’t have errors, you may look a message like this:
==21624== ==21624== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ==21624== malloc/free: in use at exit: 15646 bytes in 13 blocks.
I will try to explain more valgrind messages in other post.
dynamic languages
When reference counts marks the object as being used, and you don’t really are using it, you have a memory leak. The common way of execution for PHP scripts is that they are always holding more and more memory. Usually the common solution for PHP scripts is that you increase the runtime memory limit for the scripts on the server by changing the value of memory_limit configuration variable. Certainly you are wrong. You can avoid the extra memory usage by releasing resources, such as unused objects and variables. A good side of PHP is that it have an unset() function, that let’s you release allocated resources — some special resources needs to be deallocated using special functions, such as imagedestroy(). And really, PHP do not have a any kind of garbage collector, it just releases the allocated memory when the script have finished it’s execution. Some extensions would help, such as xdebug.
Python have a small implementation of garbage collector and really I have not seen mistakes in it like PHP about memory leaks. Only some extensions — written in C and C++ have some memory leaks. Here applies the same logic, you must reach a reference count of zero to let the objects being released. Python have a well documented Memory Management implementation.
Not much to say, just be careful with dynamic languages and it’s implementations, because many of them are extensible, many of their extensions would have memory leaks. PHP is a separate case… many people do not call it a language.
vm driven languages
Most of them have a garbage collector implementation. Do not tell me that Java is safe on this topic, or C# .NET is safe too. Just look at one of my previous posts, and then think a little. If Java, and other languages having a garbage collector implementation are really safe, why you can look live errors on the Internet as the OutOfMemoryException… The reason is simple: they have memory leaks, but not they really. Instead we have developers that have trusted the slogan that says "programming in vm driven languages is safe, don’t worry about memory". And then you have your JEE server or Application Server running the famous OutOfMemoryException, and you nearly to the quick and dirty solution like increasing the memory limits for your server.
Usually, more honest providers, let you know that the best way to mark an object as eligible to release it’s memory, is to set the object value to null. Then, the object reference count would reach zero, and the object will be released by the garbage collector. Java, Mono (use the source Luke!) and .NET have a well documented garbage collectors. Just learn how are made! And you will avoid common mistakes on this topic.
finally
Do not forget to release the unused resources…