Table of Contents

Real life:

Fixed 1 out of 99 bugs in a project. 117 to go…

Have you experienced something similar? Although it’s impossible to write bug-free code, there are tools and practices to lower the rate of mistakes.

Today, I’d like to run through a gigantic list of freely available resources from the PVS-Studio Team who works with bugs analysis on a daily basis.

Promo note: This article is sponsored by PVS Studio. Written by me.

Intro  

The Russian team behind PVS-Studio is, I think, well known in our C++ world. They not only maintain the static code analysis tool, but they also run a few blogs with tons of good stuff about programming.

And they have that funny rainbow-puking unicorn as their logo! :)

With this post, I don’t want just to sell info about their tool. I believe they have much more to offer.

What I like about the PVS-Studio Team is that they share their experience with the community. Plus, they have a unique, sometimes controversial style of writing, so it’s also a good read (for example a year ago they took over the internet :)).

From hundreds of articles I’ve selected a few and categorized them.

Here are the three main sections:

  • Code analysis: How it works? Why is it so important? Dynamic or static?
  • Repository of bugs: Whenever you created a bug, for sure you’re not the first and many before you have might experienced a similar problem. So why not learn from the “past” and other projects?
  • Guidelines: The PVS-Studio Team also does a lot of bug analysis, and they share many guidelines that can be directly applied to your code.

But first, let’s introduce the company.

About PVS  

Andrey Karpov (@Code_Analysis) and Evgeniy Ryzhkov (@evg_viva64) started the PVS-Studio company around 11 years ago, in 2006.

On 31st December Viva64 1.00 was released! The tool would help you porting projects from 32 bit into 64 on Windows.

With a lot of bumps on their entrepreneurial road, changing plans and financial struggles they managed to pursue their goals and improve the product. Currently, the company has more than 20 people on board, and the analyzer helps with bug detection in C++ projects, Windows, and Linux. Recently the tool can also work with C#. PVS-Studio is written in C, C++, and C#.

If you want to read the whole story behind the product, read here: PVS-Studio project - 10 years of failures and successes or Founder’s Advice. Evgeniy Ryzhkov.

Understanding the static analysis  

When you compile a source file, you might end up with a lot of compiler warnings. A common practice is to fix them and have zero warnings policy.

But, is that enough to have a safe and bug-free code? Definitely not.

So, what is the static analysis and why it’s better than the compiler warnings?

You can read more in this article. But briefly:

  • Code analysis is not the compiler’s primary task.
  • Using different compilers for analysis is difficult yet advisable.
  • Compilers span a narrow range of most common bugs.
  • Static analyzers only specialize in code analysis.
  • Static analyzers provide a wide range of diagnostic rules.
  • Certain diagnostics imply inevitable false positives due to their nature.
  • You can use different analyzers independently, regardless of what compiler you use.

As you can see static analyzers also works on source files, but they specialize in picking little nuances and reporting as many hints as possible. Of course, such processing takes more time than just the compilation.

Here are some articles that describe the process and the approach in detail:

It’s also worth mentioning that even John Carmack wrote/spoken about the importance of code analysis. For example, you can read his article here Static Code Analysis - by John Carmack! (reposted on PVS blog).

Ok, so far we’ve mentioned the static analysis, but why not use only dynamic bug deduction?

For instance, when you use Valgrind you can find a lot of leaks, Access Violations or other runtime errors.

In the post: Static and Dynamic Code Analysis Andrey Karpov explains that we should use both tools as they usually complement each other. Not to mention that it’s not that easy to execute the dynamic analysis, as you need the infrastructure, tests and often need to run the binaries with a different set of input data. More detail in another post: terminology: Dynamic code analysis.

Of course, PVS Studio has a few competitors in the field of C++ code analysis. For instance, You can read about them here: An Overview of Static Analyzers for C/C++ Code. Or a comparison with freely available CppCheck: Cppcheck and PVS-Studio compared and Why I Dislike Synthetic Tests.

I haven’t used the paid tools much, but around a year ago I started using code analysis from Visual Studio. It usually reports like 10…20x more warnings than the compiler! While it’s probably not the best tool around, you can use the Community version for free. PVS Team made a few comparisons against their reports: Comparing Analysis Capabilities of PVS-Studio and Visual Studio 2015’s Analyzer.

The database of bugs  

As one of their promotional strategies, the PVS-Studio Team analyses a lot of open source projects. They’ve managed to build a large list of common bugs and error-prone patterns. The approach created “the database of bugs.”

The database contains bug id, description, examples:

You can see a list of projects that exposed the bug, and read an expanded description. This might be a useful and educative resource.

The bugs repository is located here:
Errors detected in Open Source projects by the PVS-Studio developers through static analysis
.

The company claims to have found 10k bugs: We found over 10000 bugs in various open-source projects.

BTW: I’ve just got an idea that such a bug list provides a good way to start doing open source projects. Just pick a bug/warnings, see if it’s still there in the project and submit a fix.

Projects checked  

As mentioned, the PVS-Studio Team has reviewed a lot of projects, here’s a list of a few that caught my attention:

Guidelines  

What can we do with the analyzed bugs?

It would be best to learn from them and avoid error prone patterns.

The PVS-Studio Team gives another valuable resource: guidelines.

For example, If you’re brave you can read all of the: The Ultimate Question of Programming, Refactoring, and Everything. That’s a mega post with guidelines about programming. I had already mentioned it in my article last year: C++ (Core) Coding Guidelines:

The book (the article) covers 42 topics. In spite of the simple titles of the
chapters, the bugs found are various and non-standard. In
addition to that, the text provides a lot of links to interesting
materials that give more details on topics. To make more use of this
book, please don’t hurry and go to the links provided.

For example, we have tips on modern C++ “38. Use nullptr instead of NULL from now on” and “15. Start using enum class in your code, if possible”. BTW: about modern C++ they have a separate article: How to avoid bugs using modern C++.

But the “Ultimate… ” article also contains more complex and practical cases:

  • “11. Don’t try to squeeze as many operations as possible in one line”:
    • For example return c * ((t = t / d - 1) * t * t + 1) + b; it’s not only hard to read, but also contains what might lead to undefined behaviour (order of params evaluation).
  • “12. When using Copy-Paste, be especially careful with the last lines” - an interesting effect where statistically there’s a high chance of making a typo/mistake.
  • “13. Table-style formatting”
  • “25. Do not compare ‘this’ to nullptr anymore”:
  • “32. Dangerous printf”
    • If you still need to use printf don’t write code like printf(File.getloc().name().c_str()); as it might lead to security issues.
  • “35. Adding a new constant to enum don’t forget to correct switch operators.”

The whole guide focuses on practical patterns, even code formatting. Sometimes it’s on a different level than high-level guidelines like C++ Core Guidelines. Worth checking that list against your code.

Also, as the PVS-Studio originally started as a tool for checking 64-bit errors, the Team prepared a detailed guide on 64-bits: Lessons on development of 64-bit C/C++ applications (single file).

Another article worth mentioning:

  • The Evil within the Comparison Functions - in a sample of simple code we’ll just see simple statements like if (a > b) { } or if (checkVars()) { }. Clean and nice. But the reality is different as we often see a code with 2… 3 or even more lines of conditions, joined with some logical operation. It’s so easy to make an error in such expressions.

Q&A with Andrey Karpov, CTO?  

BF: How did you start with programming? (Was C++ your first language?)

Andrey : My first computer was a soviet Apogee BK 01 (home computer).

https://geektimes.ru/post/279126/

https://ru.wikipedia.org/wiki/%D0%90%D0%BF%D0%BE%D0%B3%D0%B5%D0%B9_%D0%91%D0%9A-01

Unfortunately, I can’t give a description in English. Well, this is approximately the same as ZX Spectrum, only simpler. I had only 2 languages for it: Basic and Assembler. There were other languages for it, but I had only those tapes. So everything has been predetermined without me:).

In the beginning I learned Basic. It had plenty of restrictions. And when it wasn’t enough of the abilities, I learned and started programming in Assembler. Then there was a 80286 computer, learning Pascal, etc., but that’s another story. I got to know C++ (Borland C++ 3.1) only in the university and was learning it myself, as it wasn’t taught during the first years.

BF: Do you still write code for your tool or you’re mostly responsible for the management?

Andrey : I like to code in C++, but I haven’t participated in writing the analyzer core for about a year. I just don’t have time for this. Basically, I run Visual C++, when I need to try something. Usually this is related to users support or there’s something you should experiment when writing an article.

BF: Why C++is so hard to analysis?

Andrey :You need to consider a lot of subtleties. Having selected the wrong pattern, you need to make many exceptions. A simple example:

a = a;

Does it seem to be a typo or an unequivocal error? Not at all. This makes sense if these are volatile variables. It is not necessary to issue a warning. Or it is necessary to check whether this is the implementation of the macro with names such as UNREFERENCED_PARAMETER. If it’s such a macro, then it is not necessary to complain. And so on. And it was only the simplest case. In complex diagnostics, special cases are numbered in tens. The way static analyzers fight against false positives, and why they do it: https://www.viva64.com/en/b/0488/

It is necessary to support all new and new constructions that appear in C++xx (C++11, C++14, C++16, …).

Moreover, in C++, there is such a horror as goto and switch. These are very complex operators for analysis. They spoil everything. :)

Summary  

I hope you weren’t too bored by this sponsored post.

As you can see marketing strategies, like that of PVS-Studio, can be also fun and provide real value to users/readers. With the bug database, a multitude of articles about checked projects and the resulting guidelines, you can learn a lot about coding.