📜 ⬆️ ⬇️

Yes, PVS-Studio can detect memory leaks

memory leak

We are often asked if the PVS-Studio static code analyzer is able to detect memory leaks (memory leaks). In order not to write similar texts in letters many times, we decided to give a detailed answer in the blog. Yes, PVS-Studio can detect memory leaks and other resources. For this purpose, several diagnostics are implemented in PVS-Studio and the article will demonstrate examples of error detection in real projects.

Detection of memory and resource leaks


Memory leak is a process of uncontrolled decrease in the amount of free RAM or virtual memory of a computer associated with errors in running programs that do not free up unnecessary memory sections in time. According to CWE, memory leaks are classified as CWE-401 .

Memory leaks are a type of resource leak error. An example of a different type of resource leak is an error called a file handle leak: a file is opened, but not closed, and the handle is not returned to the operating system. According to CWE, such errors can be classified as CWE-404 .

Leaks of memory or other resources can lead to Denial of Service errors.
')
To detect memory leaks and other resources, tools of dynamic and static code analysis are used. The PVS-Studio analyzer belongs to the number of such tools.

The following diagnostics are implemented in PVS-Studio to detect the class of errors under consideration:


Examples


Let's look at a few examples of detecting memory leaks in the code of open projects with the PVS-Studio analyzer.

Example N1

NetDefender project. PVS-Studio warning: V773 The 'm_pColumns' pointer was not released in destructor. A memory leak is possible. fireview.cpp 95

Notice that two objects are created in the constructor:


CFireView::CFireView() : CFormView(CFireView::IDD) { m_pBrush = new CBrush; ASSERT(m_pBrush); m_clrBk = RGB(148, 210, 252); m_clrText = RGB(0, 0, 0); m_pBrush->CreateSolidBrush(m_clrBk); m_pColumns = new CStringList; ASSERT(m_pColumns); _rows = 1; start = TRUE; block = TRUE; allow = TRUE; ping = TRUE; m_style=StyleTile; } 

In the destructor, only one object is destroyed, the address of which is stored in the m_pBrush variable:

 CFireView::~CFireView() { if(m_pBrush) { delete m_pBrush; } } 

About the variable m_pColumns apparently just forgotten. As a result, a memory leak occurs.

Example N2

Project Far2l (Linux port of FAR v2). The error is interesting because it is immediately detected by two different diagnostics of PVS-Studio:


 BOOL WINAPI _export SEVENZ_OpenArchive(const char *Name, int *Type) { Traverser *t = new Traverser(Name); if (!t->Valid()) { return FALSE; delete t; } delete s_selected_traverser; s_selected_traverser = t; return TRUE; } 

The return statement and the delete statement are mixed up in places. As a result, the delete statement is never executed. The analyzer warns about this by generating a message about an unreachable code and a message about a memory leak.

Example N3.

Firebird project. PVS-Studio warning: V701 realloc () possible leak: when realloc () fails in allocating memory, original pointer 's-> base' is lost. Consider assigning realloc () to a temporary pointer. mstring.c 42

 int mputchar(struct mstring *s, int ch) { if (!s || !s->base) return ch; if (s->ptr == s->end) { int len = s->end - s->base; if ((s->base = realloc(s->base, len+len+TAIL))) { s->ptr = s->base + len; s->end = s->base + len+len+TAIL; } else { s->ptr = s->end = 0; return ch; } } *s->ptr++ = ch; return ch; } 

This function is intended to add a character to the string. The buffer that is used to hold the string is increased by calling the function realloc . The error is that if the realloc function cannot increase the size of the memory buffer, a memory leak will occur. The reason is that if there is no memory block of sufficient size, the realloc function returns NULL and, at the same time, it does not release the previous memory buffer. Since the result of the function is immediately recorded in the variable s-> base , there is no way to release the previously allocated block.

You can fix the error by adding a temporary variable and calling the free function:

 int mputchar(struct mstring *s, int ch) { if (!s || !s->base) return ch; if (s->ptr == s->end) { void *old = s->base; int len = s->end - s->base; if ((s->base = realloc(s->base, len+len+TAIL))) { s->ptr = s->base + len; s->end = s->base + len+len+TAIL; } else { free(old); s->ptr = s->end = 0; return ch; } } *s->ptr++ = ch; return ch; } 

Static and dynamic analysis


Using the example of PVS-Studio, it can be seen that static analyzers can detect various types of resource leaks. However, for the sake of justice, it should be noted that, in general, static analyzers lose out in the area of ​​leak detection by dynamic code analyzers.

To find an error, static analyzers must track how pointers are used and this is a very difficult task. Pointers can be tricky transferred between functions and to the analyzer, by studying the source code, it is difficult to track if there is a memory leak or not. In some cases, this is not possible at all, since the analyzer does not know what input data the program will work with.

Dynamic analyzers find memory leaks or resources much easier. They do not need to track anything. They just need to remember a place in the program where some resource is allocated and check if it is free before the end of the program. If not, an error was found. Thus, dynamic analyzers more accurately and reliably detect various types of leaks.

It does not at all follow from the above that dynamic analysis is more powerful than static. The methodology of dynamic analysis, like the methodology of static analysis, has both advantages and disadvantages. Specifically, in the area of ​​leakage, dynamic analyzers are more powerful. In other areas, for example, in the search for typos or unreachable code, they are ineffective or completely useless.

Do not contrast static and dynamic analysis. These techniques do not compete, but complement each other. Solving issues of improving the quality and reliability of the code, you should use both types of tools. I wrote about this many times and I don’t want to repeat myself. For those who want to understand this issue in more detail, I offer several links:


Conclusion


The PVS-Studio static code analyzer is able to detect a wide range of errors related to memory leaks and other resources. Use it regularly to fix bugs at the stage of writing code or during nightly builds of a project:
The PVS-Studio team wishes you a reckless code.



If you want to share this article with an English-speaking audience, then please use the link to the translation: Andrey Karpov. Yes, PVS-Studio Can Detect Memory Leaks

Source: https://habr.com/ru/post/343508/


All Articles