The first keynote at CppCon this year was Bjarne Stroustrup (who invented the C++ language) announcing the C++ Core Guidelines. They are on Github and once he announced them, as Herb Sutter reported in the second keynote the very next day, they quickly became a trending topic across all languages. Here is a description of the guidelines from there:
The C++ Core Guidelines are a collaborative effort led by Bjarne Stroustrup, much like the C++ language itself. They are the result of many person-years of discussion and design across a number of organizations. Their design encourages general applicability and broad adoption but they can be freely copied and modified to meet your organization's needs.
The aim of the guidelines is to help people to use modern C++ effectively. By "modern C++" we mean C++11 and C++14 (and soon C++17). In other words, what would you like your code to look like in 5 years' time, given that you can start now? In 10 years' time?
The guidelines are focused on relatively higher-level issues, such as interfaces, resource management, memory management, and concurrency. Such rules affect application architecture and library design. Following the rules will lead to code that is statically type safe, has no resource leaks, and catches many more programming logic errors than is common in code today. And it will run fast - you can afford to do things right.
To me, these guidelines are the key to getting across my fundamental message that C++ does not have to be hard, scary, complicated, or dangerous. The language may still say “it’s your foot!” but the guidelines, and the tools they can drive, are quite the opposite.
You probably know that Visual Studio has a static analyser built in. (You should, anyway, I’ve blogged about it.) It will catch things like this:
int* p = nullptr; *p = 10;
But it doesn’t mind things like this:
int arr; int* p2 = arr;
Two lines, two violations of the guidelines – I’m not initializing any of the elements of arr, and then I am using its address as a regular old pointer. Now, there’s nothing wrong with regular old pointers – some people have got quite a hate on for them with the rise of genuinely smart pointers, but pointers are fine. Using pointers to control lifetime isn’t fine, because it’s impossibly difficult. But pointers themselves are fine. What’s not fine here is the “decay” of an array into a pointer – folks from other languages don’t expect that at all, and some marvelous bugs have hidden behind this simple bit of helpfulness from the compiler. So there’s a guideline that says don’t do that. Specifically:
(I’m giving you a picture of code because if you want to copy and paste you should go to the live, always updated, guidelines on github.)
This guideline is part of a “profile” – a particular set of rules that are designed to be enforced and that are supported by tools. Well, when I say tools I might be overstating the case a little. There’s just one tool at the moment, but that could be enough!
This tool, C++ Core Checker, is on the NuGet Gallery. You don’t have to get it from there though. You get it, and use it, from inside Visual Studio 2015. Any version will do. If you don’t use Visual Studio normally, just get and install the Community Edition, which is free and is ok to use for commercial purposes, from https://www.visualstudio.com/ . (Need the fine print? if you’re using it as a person, you can do whatever you like. If you work for a company with less than 250 PCs and less than a million dollars US in revenue, again you and up to 4 of your coworkers can use it for whatever you like. If you work for an “enterprise” company then any and all of the employees can still use it for learning purposes or to work on open source.) Note that Visual C++ isn’t part of the Typical install, so you’ll need to choose Custom and select Visual C++:
So once you have Community Edition or some edition of Visual Studio, make a console application and put in the two bad lines of code. Build it and then also run static analysis on it (On the Analyze menu, choose Run Code Analysis, On Solution.) You won’t get any warnings or errors. That’s your pre-guidelines life. You’re doing something inappropriate and nobody is telling you.
Now, add the checker to your solution. This is solution-by-solution, not a change to how Visual Studio does static analysis. On the Tools menu, choose NuGet Package Manager, Package Manager Console. In the console window that appears, type Install-Package Microsoft.CppCoreCheck and press enter. You will see output like this:
Attempting to gather dependencies information for package 'Microsoft.CppCoreCheck.14.0.23107.2' with respect to project 'ConsoleApplication1', targeting 'native,Version=v0.0'Attempting to resolve dependencies for package 'Microsoft.CppCoreCheck.14.0.23107.2' with DependencyBehavior 'Lowest'Resolving actions to install package 'Microsoft.CppCoreCheck.14.0.23107.2'Resolved actions to install package 'Microsoft.CppCoreCheck.14.0.23107.2'Adding package 'Microsoft.Gsl.0.0.1' to folder 'c:\users\kate\documents\visual studio 2015\Projects\ConsoleApplication1\packages'Added package 'Microsoft.Gsl.0.0.1' to folder 'c:\users\kate\documents\visual studio 2015\Projects\ConsoleApplication1\packages'Added package 'Microsoft.Gsl.0.0.1' to 'packages.config'Successfully installed 'Microsoft.Gsl 0.0.1' to ConsoleApplication1Adding package 'Microsoft.CppCoreCheck.14.0.23107.2' to folder 'c:\users\kate\documents\visual studio 2015\Projects\ConsoleApplication1\packages'Added package 'Microsoft.CppCoreCheck.14.0.23107.2' to folder 'c:\users\kate\documents\visual studio 2015\Projects\ConsoleApplication1\packages'Added package 'Microsoft.CppCoreCheck.14.0.23107.2' to 'packages.config'Successfully installed 'Microsoft.CppCoreCheck 14.0.23107.2' to ConsoleApplication1PM>This changes your project settings so that analysis runs this Core Checker for you. Repeat the analysis step and this time the new tool will run and you will get output like this:------ Rebuild All started: Project: ConsoleApplication1, Configuration: Debug Win32 ------ stdafx.cpp ConsoleApplication1.cpp ConsoleApplication1.vcxproj -> c:\users\kate\documents\visual studio 2015\Projects\ConsoleApplication1\Debug\ConsoleApplication1.exec:\users\kate\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp(9): warning C26494: Variable 'arr' is uninitialized. Always initialize an object. (type.5: http://go.microsoft.com/fwlink/p/?LinkID=620421)c:\users\kate\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp(10): warning C26485: Expression 'arr': No array to pointer decay. (bounds.3: http://go.microsoft.com/fwlink/p/?LinkID=620415)========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
Where it says "type.5" and there's a link, that's to the specific rule in the "type" profile that this code breaks. And where it says "bounds.3", the same - I showed a picture of bounds.3 up above.
Isn’t that great? Come on, it’s great! The tool will add more rules as we move through 2016. I’m going to have a lot more to say about the Guidelines as well. But this is a great place to start.Why not point it at some of your own code and see what happens?
Click Subscribe, then Start 10-Day trial