Line Coverage

The Code Coverage instrumentation in Visual Studio is based on binary instrumentation instead of source instrumentation.  The binary built from your code is cracked open and probes are inserted in the basic block so we can track whether each block has been executed or not.  The main benefit of binary instrumentation (as opposed to source level) is that it is source language agnostic.  We use the same PDB information the debugger uses to map locations in the binary back to source lines.  This has a few disadvantages.

First, not all PDBs are the same.  For instance, in C#, we get line and column information, but native C++ has only line information.  So if you have a loop in C# you will get coloring like this for a zero-trip check failure.

Covered ; Not Covered; Partially Covered

for (int i = 0; 1 == 2; i++)

In C++:

for (int i = 0; 1 == 2; i++)

Even though the code matches, the difference in debugging info will lead to different results.  However, for consistency in our statistics, we treat that line as "partially covered" in both versions for line statistics.  Partially covered lines are any lines with multiple blocks where some blocks are covered and some blocks are uncovered.  Since basic blocks are indivisible by definition, there is no such thing as partially covered blocks.

Another common head scratcher is the ternary "? :" operation in C#.  The debug information for this construct is not as rich, and so we don't get column information even in C#.  These will usually show up as one big solid blue line (in recent builds of whidbey).


i = (j == 3) ? false : true;

I hope that eventually we will get some of these counter-intuitive cases fixed, but in the meantime, a good rule of thumb is: "If your debugger can't break the line in to parts, neither can the code coverage colorer."