PVS-Studio by “Program Verification Systems” finds errors in your C++ code statically analyzing files in a Visual Studio solution.
Static analysis tools are a long term investment of time and money in code quality. They can find certain kinds of errors in your code, but in practice for C++ most of the time they just suggest suspicious code fragments for manual review. The balance between found errors and spurious warnings greatly depends on your own codebase. More fixed buffers, type casts and untyped functions like printf you use – more probably real errors will be found. Actually the only way to assess the usefulness of a static code analyzer for your project is to run it on your code. Reading others experiences (like John Carmack’s pursuit to static code analysis) can only prompt you to try it for yourself.
PVS-Studio can detect general C++ errors (storing a pointer to a local variable outside the scope of the variable, buffer overflow, semicolon after if/for/while), 64-bit portability errors (conversions between memsize and 32-bit types, alignment rule changes, deprecated Win64 system calls) and OpenMP errors (missing parallel/omp/for keywords, data races, throw in a parallel section). Overall more than 160 kinds of errors are detected.
You can manually start an analysis for a file, project or solution from the PVS-Studio menu in Visual Studio:
Found errors are displayed in the PVS-Studio analysis results tool window. You can see error description, jump to the code, sort and filter errors, mark an error as a false alarm:
PVS-Studio can automatically run the analysis on changed files after each build. PVS-Studio supports execution from command line and integration with TFS and other build automation systems like CruiseControl .NET and Hudson.
I’ve run PVS-Studio on my file manager. It is written mostly in high level C++ (Boost, standard C++ library, TBB) compiling cleanly with warning level 4 and with CLR extensions enabled. PVS-Studio doesn’t officially support C++/CLR, but seems to processed it successfully. The whole analysis took 8 hours on my quad core machine with Preprocessor set to VisualCPP and 3 processor’s cores used for analysis.
PVS-Studio warned me of identical sub-expressions to the left and to the right of the ‘!=’ operator in my unit tests when I test the overloaded ‘!=’ operator:
errors.assert(!(RelativePath(L"3") != RelativePath(L"3")), L"! 3 != 3");
Warned of empty exception handlers in code when I return false or empty boost::optional in case of an error:
try { boost::wregex rx(mask, boost::regex::normal | boost::regbase::icase); if (boost::regex_search(name, rx)) return true; } catch (const boost::bad_expression&) { } return false;
Warned of the .NET ‘list.Items’ pointer used simultaneously as an array and as a pointer to a single object in my unit tests:
WinForms::ListView list; … errors.assert_equals(3, list.Items->Count, L"items count with file"); if (list.Items->Count == 3){ errors.assert_equals( DirectoryPresenter::current_directory_text(), cli_to_wstring(list.Items[1]->Text), L"item 1 with file"); errors.assert_equals( std::wstring(L"1"), cli_to_wstring(list.Items[2]->Text), L"item 2 with file"); }
Warned of the identical conditional expressions of the ‘if’ operators situated alongside each other in my unit tests. In this case I agree the code can be changed to a single ‘if’ or to ‘mm.size() == 1’ in the first ‘if’:
void t_sliding_text_matches(TestErrors& errors) { scalable_vector_path_match_characteristics mm = sliding_text_matches(L"cd_doc", L"cd_"); errors.assert_equals(2u, mm.size(), L"sliding_text_matches: size"); if (mm.size() == 2){ PathMatchCharacteristics m = mm[0]; … } if (mm.size() == 2){ PathMatchCharacteristics m = mm[1]; … } }
Warned of the identical conditional expressions of the ‘if’ operators situated alongside each other in my DBC assertions:
RelativePath::RelativePath(const std::vector<FileName>& names) : names(names){ REQUIRE(!names.empty()); ENSURE(!names.empty()); }
Warned of the decreased performance when I missed to accept the ‘special_chars’ parameter by reference:
struct ExcludeSpecialChars : public boost::spirit::char_parser<ExcludeSpecialChars> { typedef ExcludeSpecialChars self_t; ExcludeSpecialChars(const std::wstring special_chars) : special_chars(special_chars){ } private: std::wstring special_chars; };
I’ve also run PVS-Studio on a part of my .NET monitor. It again found 2 empty exception handlers. Warned of an odd explicit type casting that I used for direct access of object’s memory:
// REQUIRE(data.size() == sizeof(const void*)); std::wstring PrintString::print(const std::vector<unsigned char>& data) const { const void* s = *reinterpret_cast<const void* const*>(&data[0]); if (s == NULL) return L"null"; …
As this project is ready for both 32-bit and 64-bit I turned on 64-bit checks and PVS-Studio warned me of several implicit conversions to memsize type in an arithmetic expression and of several magic numbers used. After a review I considered all these code fragments acceptable.
Overall, PVS-Studio showed it can check for non-trivial errors with not many false warnings (for example, Visual Studio code analysis gave me more than 200 warnings). The analysis process is very slow, but background incremental analysis only for changed files after each build alleviates this problem. Integration with Visual Studio works well and is very convenient.
A PVS-Studio license for 5 developers costs €3500 and not affordable to many developers. The freely available trial version hides line numbers for some errors it detects during the analysis, but the error messages and file names give enough context to locate the problematic code manually. A free license for 1 month is available for students, open source developers and bloggers.
PVS-Studio supports C/C++/C++11 applications developed in Visual Studio 2005/2008/2010. You can download the trial version from the official website.
Hello. Thank you for writing the article. But, you see, it’s been quite a while and the PVS-Studio tool has significantly developed since then. So I invite you to take a fresh look at it and perhaps you’d like to write another article. I am ready to help you with that.
To find out what new features our tool has to offer nowadays, please see this article: http://www.viva64.com/en/b/0305/ .
It describes all the main capabilities of PVS-Studio. Besides, welcome to our blog where you can learn interesting information about the tool and its development: http://www.viva64.com/en/b
Time goes on, and the article is no longer reflecting what is PVS-Studio analyzer at the moment. For instance, now the analyzer supports C# code analysis, integrates with SonarQube and so on. I would be very grateful if the author of this article responded and wrote to me (karpov [@] viva64.com). Perhaps, I’ll manage to persuade him to write a new note. 🙂