It’s frequently stated that 60% or 70% of all programming errors are memory related. So, while these numbers could be wrong, let’s assume that they are right. While algorithmic errors often show themselves easily, memory errors are far more subtle. You can reproduce an algorithmic error with a predefined set of steps. In contrast, memory errors are seldom reproducible in this way. Worse, the problems they cause happen randomly, and may not occur every time a program is run.
Why are there so many memory errors? There are many answers. The primary reason is that programs are complicated, and the way in which memory should be managed isn’t clear. Is a library function allocating its own memory, or should the program allocate it? Once it is allocated, does your program manage the memory or does the library? Something creates a pointer to something, then the memory is freed without any knowledge that something else is pointing to it. Or, and this is the most prevalent reason, a wide separation exists between lines of code, or the time when old code and new code was written. And, of course, there’s always insufficient and inaccurate documentation.
In addition, some apparent problems might be irrelevant. If the program does not free the memory allocated for a small array, it doesn’t mean much. Or, it can be more efficient not to free the memory since the operating system will free it for you when the program ends. On the other hand, if the program continually allocates memory without freeing it, it will eventually crash because there is no more memory available.