To make your C++ coding experience as safe as possible, the Microsoft C++ Code Analysis has added new checks and improved existing ones to help you prevent bugs before they find their way into your products. Some of the checks work harder than others, analyzing the code deeper by simulating runtime behavior. As such, they can find defects that are harder to find through syntactic checks alone or through data flow analysis.
It is natural that developers find it harder to find the root causes for some of these more complex warnings. Imagine a warning where the effect of the bug is detected tens or hundreds of lines below the root cause of the bug, and the code against which the defect is reported looks completely legitimate. How would you be able to quickly find the root cause and fix it?
In this blog post, we would like to reintroduce an existing Visual Studio feature that has been there to help with this challenge, and to highlight the big improvements we have made to the feature which will make it easier and more compelling to use.
Let’s review the usual challenges we have when a static code analysis check tells us there is a defect in our code. It can be best demonstrated with some example code with a known defect. The following example is intentionally made convoluted enough to demonstrate the challenge of finding the root cause for warnings from a path-sensitive check.
Running code analysis on this code will give a few warnings. One of them will be this:
test.cpp(32) : warning C33001: VARIANT 'pv' was cleared when it was uninitialized (expression 'pv').: Lines: 5, 7, 8, 9, 11, 12, 14, 16, 19, 21, 25, 26, 32
In summary, clearing a VARIANT object that was not properly initialized can result in many random problems, including crashes, memory errors, etc. More information about this specific check can be found at c33001 | Microsoft Docs. But for this discussion, let’s focus on the root cause of the defect – why does the check say we are clearing a VARIANT object that is not initialized?
The line of code to which the warning points us is completely legitimate: we must clear the VARIANT object before we are done with it. Then what is the problem? It must be that somewhere along the code flow that reaches line 32, the VARIANT object that pv points to has not been initialized.
Let’s try to find out where the root cause is. First, we will need to find out which VARIANT object pv points to. Then follow the code flow to see why that object has never been initialized. To figure those out, we will need to trace back the code flow from where the defect is reported. Because it is likely dependent on the path that the check analyzed, we will use the line numbers provided in the warning. That seems doable. However, that doesn’t seem to be the most efficient way. Imagine a similar bug is in an excessively big function. A similar warning may come with tens or hundreds of lines of code to trace back. Many of us would feel offended by such a warning, rather than helped.
This blog post is not about finding root cause by tracking back source code manually like this. So, before going any further along this path, let’s see if there is any help available.
It may not be well known, but selected warnings from some of MSVC’s C++ static analysis checks that have been there for long time always had additional information that helps with tracing back your code to identify the root causes. This additional information is called “Key Events.” A Key Event is associated with a step in the analysis code flow. It explains what has happened in that specific step. During analysis, these checks add Key Event candidates to the steps where important or interesting events occur, e.g., when a new buffer is created, etc. As a check finds a defect, it collects all relevant Key Events along the code flow that led to the defect and adds them to the warning. Some common events are also added as Key Events – e.g., when a relevant variable is initialized or updated, when code flow branches, etc.
Here is an example of a warning with Key Events from one of those older checks as they are presented in the Error List. You could get these by clicking on the expansion triangle icon in the left-most column of the warning:
As you can see, these Key Events add rich information to the warning, making it very easy to follow the code and understand what is going on along the code flow of the analysis.
We believe in the value of Key Events for our customers. So, we decided to remove the hinderances in making it available for more checks. We also made it a lot easier to use.
To solve the first problem, we added equivalent support to our newer engine, allowing many newer checks to add Key Events to their warnings with little effort. This was done earlier, and new checks have been adding Key Events to their warnings. As of the release of Visual Studio 2022 version 17.4 Preview 2 we have augmented many checks with Key Events, including warnings for:
- Enum misuse as buffer index: C33010 and C33011
- VARIANT object misuse: C33001 ~ C33005
- Concurrency problems: C26100 ~ C26167
We will add Key Events to even more warnings in the upcoming Visual Studio releases.
Visual Studio 2022 version 17.4 Preview 2 comes with big improvements in presentation of the Key Events.
Key Events used to be presented inside the Error List window as shown earlier. Usually, real estate of Error List is very limited to present a warning with a large number of Key Events. Also, it was hard to interact with the Key Events in the list, due to missing features and bugs.
First, we redesigned the way Visual Studio presents the Key Events for MSVC C++ static analysis warnings. Key Events will now be presented outside of Error List window, in their own window as follows:
You can open this window by selecting the warning with double clicking or pressing enter key, or clicking the small window icon on the left-most column of the warning entry in the Error List. This window is like any other tabbed window – it can be docked, floated, resized, or added to the tabbed windows. Selecting a Key Event in this window highlights the corresponding source line. Keyboard navigation among the Key Events is improved in this window, and source code highlighting follows the selected Key Event.
This will make it a lot easier to review the Key Events and navigate through them along with the corresponding source code, often greatly reducing the time to find the root cause of the defect. For the example code and the warning, now it is a lot easier to tell pv is pointing to pvTmp, and pvTmp is pointing to v2, which was never initialized in the code flow.
We have teamed up with the developers of the SARIF Viewer Extension for Visual Studio. Some of you may have tried its older versions before. If you haven’t tried it before, now is a good time to get the latest release and give it a try, as we believe it will greatly enhance your productivity with the improvements we made to the extension.
Visualization of Key Events in SARIF Explorer window
Through close collaboration among related teams, we greatly improved the functionality of the SARIF Viewer Extension for Visual Studio. When installed and enabled this extension can now display Key Events in its SARIF Explorer window without requiring you to find and open the SARIF file. You just need to select the warning that has the small window icon on the left-most column by double clicking or pressing the enter key, or clicking the small window icon. Visual Studio will let SARIF Viewer Extension display the Key Events, instead of its own pop-up window:
If you select a Key Event in the SARIF Explorer window, the corresponding source code in the Text Editor window will be highlighted with slightly darker color. If you select source code that is highlighted in the Text Editor window, the corresponding Key Event will be highlighted in the SARIF Explorer window.
Source code adornment with Key Events
There is even greater news. The SARIF Viewer Extension for VS now displays Key Events right next to the source code they belong to. This will make it a lot easier to find the root cause by allowing review of the source code along with detailed explanation on what the check discovered or assumed at each of the steps of the analysis path that leads to the defect.
Here is an example:
To get the essential help from Key Events, you don’t need to do anything. Visual Studio comes with full features to present and let you interact with Key Events. Just install or upgrade your Visual Studio to VS 2022 17.4 Preview 2 or later.
To enjoy the new Key Events feature to its full extent in your day-to-day work, also install or upgrade your SARIF Viewer Extension to the latest version. Go to “Extensions > Manage Extensions,” and search for “Microsoft SARIF Viewer 2022”. As of this writing, version 184.108.40.20606 is available. Any version newer than that should work:
To enable or disable “text adornment” with Key Events, please go to “Tools > Options… > SARIF Viewer” and select/unselect “Enable Key Event text adornments in the editor” option. It is enabled by default:
This is not the final destination for the Key Events feature. Instead, it is only a new starting point for greater improvements. For example, we are working on making the Key Events more relevant to the defect, e.g., by eliminating older assignments that do not contribute to the defect. We are also looking into better navigation support among relevant Key Events. As some of you may already be hoping, we’d love to bring the SARIF Viewer Extension experience into Visual Studio, without requiring installation of the extension.
We are very much interested in your feedback to continue to improve this experience. The comments below are open. Feedback can also be shared through the Developer Community. You can also reach us on Twitter (@VisualC), or via email at [email protected].