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

I saw the publication that PVS did learn to analyze under Linux, and decided to try on its projects. And this is what came of it.









Content



  1. pros
  2. Minuses
  3. Summary
  4. Afterword




pros



Responsive Support



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







Clear enough documentation



It was possible to start the analyzer without any problems. Help for console commands is also available (although there are complaints, see the Cons section).







Multi-threaded analysis capability



The analyzer has a “standard” option -j



, which allows analyzing 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 tips next to lines in the code and links to descriptions of diagnostics .







Easy assembly integration



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







Good diagnostic descriptions



If you generate output in fullhtml



mode, then each message has a link to a description of the diagnostics, with explanations, code examples and additional links.









Minuses



C ++ Language Analyzer Ignorance



Unfortunately, PVS sometimes errs in syntax and generates false positive messages with perfectly correct code.







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, the keyword auto



can mean void



, that's why auto . But PVS issued these 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 face 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 long enough, and sometimes it happens 504 Gateway Time-out .







Tongue



All descriptions are in Russian, that's great. But the 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 the diagnostics immediately in Russian. I did not find such an opportunity in the interface.







Inconvenient to work with diagnostic levels through the console



To begin with, the two commands used ( pvs-studio-analyzer



and plog-converter



) have different diagnostic job formats.







The help for 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 understand where to add ("adding the values") keys. Tried to list with a comma:







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





I 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 you need to summarize , not add values. For example, to get general diagnostics, diagnostics for microoptimizations and MISRA, you need to sum them (4 + 8 + 32 = 44):







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





Using bitmasks in user interfaces is usually a bad idea. All this could be summarized inside, and the user set a set of flags.







In addition, there is also the plog-converter



utility, which generates human-readable information about static analysis. She has other troubles.







Help for the plog-converter



program reports:







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





Some kind of “levels” appeared here, which had never been seen before, and I also did not find anything about them in the documentation.







In general, it is not clear. Therefore, I set everything to the maximum.







A bunch of stupid swearing at Catch



Two of the three projects I analyzed use the Catch2 unit testing library . And the lion's share of messages (!!! 90 of 138 in one and 297 of 344 in another !!!) have the following form:







Catch2







Doesn't consider multithreading



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







Multithreading







However, can a static analyzer take this into account at all? I do not know.









Summary



PVS did not find a single real mistake in my open projects Burst and Proxima , as well as in a working draft, which I, for obvious reasons, can not present. However, it should be borne in mind that some flaws have already been caught and fixed earlier using Cppcheck and scan-build



.







In general, the impression of all these analyzers is about the same: yes, they catch something, sometimes even something important, but on the whole the compiler is enough.







It is possible (and I personally am pleased to think so) that our team uses such software development practices that allow us to generate a minimum amount of shit. 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 so as not to shoot anyone's legs and not rake on the forehead.







Use compiler diagnostics to the maximum



Our team uses (and advises you) 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-dependent things if there are standard analogs, and if you can’t do without them at all, wrap them in special blocks for macros (or something else) and just don’t let us compile your code in unsupported conditions.







Stick to standard operation semantics



Addition must be addition, multiplication must be multiplication, a function call must be a function call, copy must be copied, hyphenation must be carried over, the container must be iterable, the iterator must have progress ++



and dereference *



. And so on and so forth.







I think the idea is clear. There are established agreements that are not binding but that all users and readers of your code expect to see. Do not try to outwit others, or else 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, Bust).







Feel free to peek at the STL and Boost interfaces. With rare exceptions, you will see a worthy role model there.







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 the "time".







You can read more about this in my recent publication .









Afterword



In conclusion, I emphasize that I do not urge not to use PVS or any other static analyzers. But I urge you to think about how it turned out that the static analyzer constantly finds significant errors in your code.







This is only a consequence. It is necessary to search and eliminate the cause.








All Articles