Our website uses cookies to enhance your browsing experience.
Accept
to the top
close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam

Webinar: Evaluation - 05.12

>
>
>
Memory leak

Memory leak

Nov 15 2024

A memory leak is an error in the source code, when the dynamic memory allocated for a variable, array, class object, etc. is not freed and is subsequently lost, while the data persist in RAM until the program is closed.

Such errors can overload the computer and slow down the performance while the application is running. Moreover, such an application may consume memory endlessly. Because of that, the OS eventually may terminate the problematic application and all of the application's processes.

In some cases, such errors may be considered potential vulnerabilities for application-level DoS attacks in some cases. This attack exhausts the system's resource limits.

Causes of memory leaks

When an application starts, some memory is allocated for the application's process and operations. For each executed thread data structure called the stack is created. Here the program stores information about variables, function calls, and other processes and releases these data instances one by one, only in reverse order.

However, the stack size is limited and the program may request more memory that has not yet been allocated by the OS. This type of dynamic memory is called the heap.

To work with data on the heap, the program uses pointers. These are special variables that contain a RAM block's address. But unlike the stack, the heap does not automatically release memory after the data processing is complete. Therefore, the developer has to free memory manually. Moreover, if the pointer referring to the allocated memory fragment is lost, this memory cannot be released.

In C++ code, dynamic memory is allocated by the operator new. In C code, dynamic memory is allocated by the following functions: malloc, realloc, calloc, strdup, etc. The developer can release a memory block with the operator delete (C++) or the free function (C).

In large projects, functions, structures, classes constantly exchange pointers. As a result, it becomes difficult to track when memory is allocated and freed. This is what provokes memory leak errors.

Let's look at a memory leak that the PVS-Studio analyzer detected in the Augeas project:

static void xfm_error(struct tree *xfm, const char *msg) {
  char *v = msg ? strdup(msg) : NULL;
  char *l = strdup("error");

  if (l == NULL || v == NULL)
    return;
  tree_append(xfm, l, v);
}

Though the function is short, it can lead to three memory leak scenarios. Two scenarios are unlikely, but the third one is probable.

Let's discuss the first two scenarios. One of the strdup function calls returns NULL. In this case, the function returns early and the pointer returned by the other strdup call is lost. These scenarios seem unlikely, but they are still possible.

The third one is more probable. The xfm_error function expects that the value of the msg argument can be NULL. In this case the function returns early. However, the memory allocated by the strdup("error") call will be lost.

To avoid all these errors, you can rewrite the code as follows:

static void xfm_error(struct tree *xfm, const char *msg) {
  if (msg == NULL)
    return;
  char *v = strdup(msg);
  if (v == NULL)
    return;
  char *l = strdup("error");
  if (l == NULL) {
    free(v);
  }
  tree_append(xfm, l, v);
}

Unfortunately, there is more code now, and the code became cumbersome and more susceptible to errors. This is why C developers often run into errors when they manage memory.

Note. We recommend you to also read a similar article: "Four reasons to check what the malloc function returned".

Consequences of memory leaks

If you leave data in dynamic memory uncleared, RAM may run out. At this point the OS will automatically terminate the process of our program and won't save the past work. If your OS does not accommodate for this emergency shutdown (e.g. some Linux distributions require to download a special utility), the computer may freeze or slow down significantly. As a result, you would have to wait for the program's, and consequently, the computer's response to close the program properly. Sometimes the system may slow down so much that all you would be able to do is to restart the computer.

It gets much worse when other applications are integrated into the program. In this case, all related processes are terminated, including those that you've been running for your own needs.

Moreover, because of memory leaks, you may lose data that the application was using and that you were using in a related app and did not save. For example, if RAM runs out while the application was running editors and other third-party tools in the background.

How to avoid memory leaks

C and C++ developers manage memory manually, unlike C# and Java developers – the garbage collector manages the heap for them. However, the C++ language has a protection mechanism against memory leaks. It is implemented with "smart" pointers, such as std::unique_ptr, std::shared_ptr, etc.

To ensure that there are no leaks in a program, developers use dynamic analysis tools to look for bugs. In Visual Studio you can use the Debug CRT library. The _CrtDumpMemoryLeaks function is called at the program completion point. When debugging stops, you can find the leak report in the Output window's Debug pane. This library checks for any memory allocation via new or the malloc function.

You can use third-party tools that integrate into the Visual Studio environment. Visual Leak Detector is a program, that informs users about all files and code lines where leaks occurred. You can also find this program in the same Output window.

On Unix-like operating systems (Linux, macOS) you can use Leak Sanitizer. Starting with 2019, it's been also available on Windows. This tool can be used as part of the more advanced Address Sanitizer or – in standalone mode. Compile your program with the -fsanitize=leak flag to use Leak Sanitizer in standalone mode. Alternatively, indicate the -fsanitize=address flag to use Address Sanitizer. When this tool detects a memory leak, it logs the information about the leak to the standard error output stream.

The PVS-Studio static analyzer can also detect many types of memory leaks. However, static code analysis is not as accurate, as dynamic code analysis. Static analyzers check the entire program code and can detect leaks even in rarely-used code. Dynamic analyzers fail to cover the entire program code.

In cases when a leak cannot be fixed — for example, in a third-party library that does not allow access to its source code – developers can write a bug report to the library's authors, attempt to update the library or look for similar third-party libraries. If you need an exact library, you can use a separate process to execute functions that use this library. This way, memory leaks will still be formed, but you can control them by running and ending the process when needed.

Additional resources:

Popular related articles


Comments (0)

Next comments next comments
close comment form