Static analysis - from acquaintance to integration

Tired of endless code review or debugging, sometimes you think about how to simplify your life. And after a little searching, well, or accidentally stumbling across, you can see the magic phrase: "Static analysis". Let's see what it is and how it can interact with your project.

Static analysis - from acquaintance to integration
As a matter of fact, if you write in any modern language, then, without even realizing it, you passed it through a static analyzer. The fact is that any modern compiler provides, albeit a tiny, but a set of warnings about potential problems in the code. For example, when compiling C++ code in Visual Studio, you might see the following:

Static analysis - from acquaintance to integration
In this output, we see that the variable var was never used anywhere in the function. So in fact, you almost always used a simple static code analyzer. However, unlike professional analyzers such as Coverity, Klocwork or PVS-Studio, warnings provided by the compiler can only indicate a small range of problems.

If you don't know for sure what static analysis is and how to implement it, read this articlefor more details on this methodology.

Why is static analysis needed?

In a nutshell: acceleration and simplification.

Static analysis allows you to find a lot of different problems in the code: from incorrect use of language constructs to typos. For example, instead of

auto x = obj.x;
auto y = obj.y;
auto z = obj.z;

You wrote the following code:

auto x = obj.x;
auto y = obj.y;
auto z = obj.x;

As you can see, there is a typo in the last line. For example, PVS-Studio issues the following warning:

V537 Consider reviewing the correctness of 'y' item's usage.

If you want to poke this error with your hands, then try the ready-made example on Compiler Explorer: *ΠΊΠ»ΠΈΠΊ*.

And as you understand, it is not always possible to pay attention to such sections of code immediately, and because of this, you can sit down to debug for a good hour, wondering why everything works so strangely.

However, this is a clear mistake. But what if the developer wrote suboptimal code because he forgot some subtlety of the language? Or even allowed in the code undefined behavior? Unfortunately, such cases are quite common, and the lion's share of the time is spent debugging specific working code that contains typos, typical errors, or undefined behavior.

It is for these situations that static analysis appeared. This is an assistant for the developer who will point out various problems in the code and explain in the documentation why it is not necessary to write this way, what it can lead to and how to fix it. Here is an example of what it might look like: *ΠΊΠ»ΠΈΠΊ*.

You can find more interesting errors that the analyzer can detect in the articles:

Now, having read this material and convinced yourself of the usefulness of static analysis, you might want to try it out. But where to start? How to integrate a new tool into the current project? And how to introduce the team to him? You will find answers to these questions below.

Note. Static analysis does not replace or cancel such a useful thing as code reviews. It complements this process, helping to notice and correct typos, inaccuracies, and dangerous constructions in advance. It is much more productive to focus code reviews on algorithms and code understandability, rather than on looking for the wrong parenthesis or read boring comparison functions.

0. Introduction to the instrument

It all starts with a trial version. Indeed, it is difficult to decide to introduce something into the development process if you have never seen the tool live before. So the first step is to download trial version.

What you will learn at this stage:

  • What are the ways to interact with the analyzer;
  • Is the analyzer compatible with your development environment;
  • What problems are there in your projects now.

After you have installed everything you need, the first thing to do is to run an analysis of the entire project (Windows, Linux, MacOS). In the case of PVS-Studio in Visual Studio, you will see a similar picture (clickable):

Static analysis - from acquaintance to integration
The point is that static analyzers usually issue a huge number of warnings for projects with a large code base. There is no need to fix them all, since your project is already running, which means these problems are not critical. However, you you can look at the most interesting warnings and correct them if necessary. To do this, you need to filter the output and leave only the most reliable messages. In the PVS-Studio plugin for Visual Studio, this is done by filtering by error levels and categories. For the most accurate output, leave only High ΠΈ General (also clickable):

Static analysis - from acquaintance to integration
Indeed, 178 warnings are much easier to view than several thousand ...

In tabs Medium ΠΈ low often good warnings come across, however, those diagnostics that have less accuracy (reliability) are listed in these categories. More information about warning levels and options for working under Windows can be found here: *ΠΊΠ»ΠΈΠΊ*.

Having successfully reviewed the most interesting errors (and successfully corrected them), it is worth suppress remaining warnings. This is necessary so that new warnings are not lost among the old ones. In addition, a static analyzer is a helper for a programmer, not a list for bugs. πŸ™‚

1. Automation

After getting to know each other, it's time to set up plugins and integrate into CI. This must be done before programmers start using the static analyzer. The fact is that a programmer may forget to turn on the analysis or not want to at all. To do this, you need to do some final checking of everything so that unchecked code cannot get into the general development branch.

What you will learn at this stage:

  • What automation options does the tool provide;
  • Is the analyzer compatible with your build system.

Since there is no perfect documentation, sometimes you have to write in support. This is normal and we are happy to help you. πŸ™‚

Now let's move on to continuous integration (CI) services. Any analyzer can be implemented in them without any serious problems. To do this, you need to create a separate stage in the pipeline, which is usually located after the build and unit tests. This is done using various console utilities. For example, PVS-Studio provides the following utilities:

To integrate analysis into CI, you need to do three things:

  • Install the analyzer;
  • Run analysis;
  • Deliver results.

For example, to install PVS-Studio on Linux (Debian-base), you need to run the following commands:

wget -q -O - https://files.viva64.com/etc/pubkey.txt 
    | sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list 
  https://files.viva64.com/etc/viva64.list
  
sudo apt-get update -qq
sudo apt-get install -qq pvs-studio

On Windows systems, there is no option to install the analyzer from the package manager, but it is possible to deploy the analyzer from the command line:

PVS-Studio_setup.exe /verysilent /suppressmsgboxes 
/norestart /nocloseapplications

You can read more about deploying PVS-Studio on Windows systems *here*.

After installation, you need to run the analysis directly. However, it is recommended to do this only after the compilation and tests have passed. This is because static analysis usually takes twice as long as compilation.

Since the launch method depends on the platform and the specifics of the project, I will show the C ++ (Linux) variant as an example:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log
plog-converter -t errorfile PVS-Studio.log --cerr -w

The first command will perform the analysis, and the second envelopesConverts the report to text format, prints it to the screen, and returns a return code other than 0 if there are warnings. This mechanism is convenient to use to block the assembly in the presence of error messages. However, you can always remove the flag -w and don't block the assembly containing the warnings.

Note. The text format is inconvenient. It is provided simply as an example. Pay attention to a more interesting report format - FullHtml. It allows you to navigate through the code.

You can read more about setting up analysis on CI in the article "PVS-Studio and Continuous Integration" (Windows) or "How to set up PVS-Studio in Travis CI" (Linux).

Okay, you have configured the analyzer to work on the build server. Now, if someone has uploaded untested code, the verification stage will fall, and you will be able to detect the problem, but this is not very convenient, since it is more efficient to check the project not after the branches have been merged, but before it, at the pull request stage' A.

In general, setting up a pull request analysis does not differ much from the usual analysis run on CI. Except for the need to get a list of changed files. You can usually get them by querying the difference between branches using git:

git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list

Now we need to pass this list of files to the analyzer as input. For example, in PVS-Studio this is implemented using the flag -S:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log 
                            -S .pvs-pr.list

You can learn more about pull request analysis *here*. Even if your CI is not listed in the list of services mentioned in the article, you will benefit from a general section on the theory of this type of analysis.

By setting up pull request parsing, you can block commits that contain warnings, thereby creating a boundary that untested code cannot cross.

All this is certainly good, but I would like to be able to see all the warnings in one place. Not only from a static analyzer, but also from unit tests or a dynamic analyzer. For this, there are various services and plugins. PVS-Studio, for example, has plugin for integration into SonarQube.

2. Integration on developers' machines

Now it's time to install and configure the analyzer for everyday development use. By this point, you have already become familiar with most of the ways to work, so this can be called the easiest part.

As the simplest option, developers themselves can install the necessary analyzer. However, this will take a lot of time and distract them from development, so you can automate this process using an installer and the right flags. For PVS-Studio there are various flags for automated installation. However, there are always package managers like Chocolatey (Windows), Homebrew (macOS) or dozens of options for Linux.

Then you will need to install the necessary plugins, for example, for Visual Studio, IDEA, Rider etc.

3. Daily use

At this stage, it's time to say a few words about ways to speed up the analyzer in daily use. A complete analysis of the entire project takes a very long time, but how often do we change the code at once in the entire project? There is hardly a refactoring so massive that it will immediately affect the entire codebase. The number of files being modified at a time rarely exceeds a dozen, so it makes sense to analyze them. For such a situation, there incremental analysis mode. Just don't be scared, it's not just another tool. This is a special mode that allows you to analyze only changed files and their dependencies, and this happens automatically after the build if you are working in an IDE with a plugin installed.

If the analyzer finds problems in the recently changed code, it will report it on its own. For example, PVS-Studio will tell you about it with a notification:

Static analysis - from acquaintance to integration
It goes without saying that it is not enough to tell developers to use the tool. You need to somehow tell them what it is in general and how it is. For example, here are articles about a quick start for PVS-Studio, but you can find similar tutorials for any tool you prefer:

Such articles provide all the information you need for everyday use and do not take much time. πŸ™‚

Even at the stage of getting to know the tool, we suppressed a lot of warnings during one of the first launches. Alas, static analyzers are not perfect, so they give false positives from time to time. It is usually easy to suppress them, for example, in the PVS-Studio plugin for Visual Studio, just click on one button:

Static analysis - from acquaintance to integration
However, you can do more than just suppress them. For example, you can report a problem to support. If the false positive can be fixed, then in future updates you may notice that there are fewer and fewer false positives specific to your codebase each time.

After integration

So we have gone through all the stages of integrating static analysis into the development process. Despite the importance of setting up such tools on CI, the most important launch site is the developer's computer. After all, a static analyzer is not a judge who says somewhere far away from you that the code is no good. On the contrary, it is an assistant that tells you if you are tired and reminds you if you have forgotten something.

True, without regular use, static analysis is unlikely to greatly simplify development. After all, its main benefit for the developer lies not so much in the search for complex and controversial code sections, but in their early detection. Agree that finding a problem when the edits went for testing is not only unpleasant, but also very long. Static analysis, on the other hand, when used regularly, looks at each change right on your computer and reports suspicious places while working on the code.

And if you or your colleagues are still not sure whether it is worth implementing the analyzer, then I suggest you now move on to reading the article "Reasons to introduce the PVS-Studio static code analyzer into the development process". It analyzes the typical concerns of developers that static analysis will take their time and so on.

Static analysis - from acquaintance to integration

If you want to share this article with an English-speaking audience, please use the translation link: Maxim Zvyagintsev. Static Analysis: From Getting Started to Integration.

Source: habr.com

Add a comment