Independent review of PVS-Studio (Linux, C++)

I saw a publication about what PVS did learn to analyze under Linux, and decided to try it on my projects. And here's what came out of it.


Content

  1. pros
  2. Cons
  3. Results
  4. Afterword

pros

Responsive Support

I requested a trial key and they sent it to me the same day.

Fairly clear documentation

The analyzer was launched without any problems. Help for console commands is also available (although there are complaints here, see the section Cons).

Possibility of multithreaded analysis

The analyzer has a "standard" option -j, which allows to perform analysis in parallel in several tasks. This saves a lot of time.

Good visualization

Many different output formats, from text to a small web muzzle. The web face is convenient, concise, with hints next to the lines in the code and links to descriptions of diagnostics.

Easy assembly integration

All the documentation is on their website, I can only say that if your project is built using CMake, then everything is very simple.

Good descriptions of diagnostics

If you generate output in mode fullhtml, then each message has a link to a description of the diagnostic, with explanations, code examples, and additional links.

Cons

Ignorance of the C++ language by the analyzer

Unfortunately, PVS sometimes makes mistakes in syntax and generates false positive messages when code is perfectly correct.

For example, there is a function that returns void:

template <typename T>
auto copy (const void * source, void * destination)
    ->
        std::enable_if_t
        <
            std::is_copy_constructible<T>::value
        >
{
    new (destination) T(*static_cast<const T *>(source));
}

Yes, keyword auto Can mean void, that's why it auto. But PVS gave the following messages:

dynamic_tuple_management.hpp:29:1: error: V591 Non-void function should return a value.
dynamic_tuple_management.hpp:29:1: error: V2542 Function with a non-void return type should return a value from all exit paths.

Very slow site

Yes, in the web interface, next to each message, there is a link to the corresponding diagnostic description with examples. But when you click on the link, you have to wait quite a long time, and sometimes it happens 504 Gateway Timeout.

Language

All descriptions are in Russian, which is excellent. But links from the report always lead to the English version. It would be nice to be able to switch the language so that you can view diagnostics immediately in Russian. I did not find such an option in the interface.

It is inconvenient to work with diagnostic levels through the console

Let's start with the fact that the two commands used (this is pvs-studio-analyzer ΠΈ plog-converter) different formats for setting diagnostics.

Help to pvs-studio-analyzer reads:

-a [MODE], --analysis-mode [MODE]
    MODE defines the type of warnings:
    1 - 64-bit errors;
    2 - reserved;
    4 - General Analysis;
    8 - Micro-optimizations;
    16 - Customers Specific Requests;
    32 - MISRA.
    Modes can be combined by adding the values
    Default: 4

For a long time I tried to figure out where to go add ("adding the values") keys. Tried to list with commas:

pvs-studio-analyzer analyze ... -a 1,4,16

Tried to register the key several times:

pvs-studio-analyzer analyze ... -a 1 -a 4 -a 16

And only then I realized that these are bit masks! And need sum upAnd not add values. For example, to get general diagnostics, diagnostics for micro-optimizations and MISRA, you need to sum them up (4 + 8 + 32 = 44):

pvs-studio-analyzer analyze ... -a 44

Using bitmasks in user interfaces is generally bad form. All this could be summed up inside, and the user could set a set of flags.

In addition, there is another utility plog-converter, which generates human-readable static analysis information. She has other troubles.

Help for the program plog-converter reports:

-a, --analyzer            Specifies analyzer(s) and level(s) to be
                          used for filtering, i.e.
                          'GA:1,2;64:1;OP:1,2,3;CS:1;MISRA:1,2'
                          Default: GA:1,2

Some β€œlevels” appeared here that weren’t anywhere before, and I didn’t find anything about them in the documentation either.

In general, it is not clear. So I set everything to the max.

A bunch of stupid swearing on Catch

Two of the three projects I analyzed use the unit test library catch2. And the lion's share of messages (!!! 90 out of 138 in one and 297 out of 344 in the other !!!) look like this:

Independent review of PVS-Studio (Linux, C++)

Doesn't take multithreading into account

There are many false positives about supposedly unchanged variables or infinite loops, while working with these variables occurs from different threads, and if this were not the case, then the unit tests would not work.

Independent review of PVS-Studio (Linux, C++)

However, can a static analyzer even take this into account? Don't know.

Results

PVS didn't find any real bugs in my open projects Burst ΠΈ Proxima, as well as in the working draft, which I, for obvious reasons, cannot present. True, it should be borne in mind that some flaws have already been caught and fixed earlier with the help of Cppcheck ΠΈ scan-build.

In general, the impression from all these analyzers is approximately the same: yes, they catch something, sometimes even something important, but in general the compiler is enough.

It is possible (and I personally like to think so) that our team uses software development practices that allow us to generate the minimum amount of shit code. It is better not to create problems than to overcome them heroically.

Therefore, I take the liberty of giving some advice on how to write in C ++ in such a way that you don’t shoot anyone in the legs and don’t rake their foreheads with a rake.

Make the most of compiler diagnostics

Our team uses (and advises you on) the following compilation options:

-Werror

-Wall
-Wextra
-Wpedantic

-Wcast-align
-Wcast-qual
-Wconversion
-Wctor-dtor-privacy
-Wenum-compare
-Wfloat-equal
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wredundant-decls
-Wsign-conversion
-Wsign-promo

Include them in your project, learn a lot about your code.

Stick to the Standard

Try not to use platform-specific things if there are standard analogues, and if you absolutely cannot do without them, wrap them in special blocks for a macro (or something else) and just don't let your code compile in unsupported conditions.

Stick to standard operation semantics

Addition must be addition, multiplication must be multiplication, function call must be function call, copy must be copy, carry must be carry, container must be iterable, iterator must be advancing ++ and dereferencing *. And so on and so forth.

I think the idea is clear. There are established conventions that are not binding, but that all users and readers of your code expect to see. Don't try to outsmart others, or you'll outsmart yourself.

Write compatible code

First of all, I mean the standard library. It is highly desirable that the interfaces of your classes and functions can be used with standard and other libraries (for example, Boost).

Feel free to peek into the STL and Boost interfaces. With rare exceptions, there you will see a worthy example to follow.

Make the most of open tools

For the same static analysis, there are at least two open free tools that are connected to any project with the CMake build system at the expense of β€œtimes”.

You can read more about this in my recent post..

Afterword

Finally, I would like to emphasize that I am not advocating not to use PVS or any other static analyzers. But I encourage you to think about how it happened that the static analyzer constantly finds significant errors in your code.

This is just a consequence. It is necessary to find and eliminate the cause.

Source: habr.com

Add a comment