No use preaching "careful coding". Bugs have always been and will always be there. Everybody knows bugs should be fixed. People forget that bugs should be fixed at the lowest cost possible in terms of time and money!
2. Bugs Have Always Been and Will Always
Be There
• No use preaching "careful coding"
• Bugs have always been and will always be there
• Everybody knows bugs should be fixed
• People forget that bugs should be fixed at the lowest cost possible in
terms of time and money!
3. Too Many Heroes Are a Bad Sign
• You may enjoy telling people how your team spent a week heroically
hunting for a bug
• But the fact that your team has to perform such feats does it no credit
This city code needs a hero!
4.
5.
6. The Sooner You Fix, the Better
• Depending on the bug pattern, fixing at the coding stage is 10–100
times cheaper than after the release
• Various techniques are available:
• code review
• unit testing (or TDD)
• testing a new feature by its author
• dynamic code analysis (a variation of testing)
• static analysis, which will be discussed further
7. What Code Review Is
• Code is examined by several programmers
• Ideally, they shouldn’t be using a computer
• They give their comments and
advice on what to fix and improve
8. Pros of Code Review by Humans
• You can find complex bugs
• You can find high-level defects (such as slow algorithms)
9. Cons of Code Review by Humans
• There could be bugs none of the reviewers is aware of
• It’s expensive
• Humans get tired fast
10. Static Analysis as a Compromise
• Pros of analyzers:
• they check the entire code
• they don’t get tired
• they can recognize tricky bug patterns
• Cons:
• they are just programs, not an AI
• They are definitely useful thanks to immediate detection of bugs
• Analogy: the spell check in Microsoft Word.
11. Static Analysis Tools
• We’ll take PVS-Studio as an example
• But there are many other tools to fit any taste:
• FxCop
• Klocwork
• Parasoft
• SonarQube
• Veracode
• More: https://en.Wikipedia.org/wiki/List_of_tools_for_static_code_analysis
12. A Few Examples: A Typo
static bool AreEqual (VisualStyleElement value1,
VisualStyleElement value2)
{
return
value1.ClassName == value1.ClassName &&
value1.Part == value2.Part &&
value1.State == value2.State;
}
PVS-Studio: V3001 There are identical sub-expressions 'value1.ClassName' to the left and to
the right of the '==' operator. ThemeVisualStyles.cs 2141
Mono
13. A Few Examples: Coding in a Hurry
void IBackgroundTask.Sweep()
{
....
// Don't flood the database with progress updates;
// Limit it to every 5 seconds.
if ((_clock.UtcNow - lastUpdateUtc).Seconds >= 5)
{
....
PVS-Studio: V3118 Seconds component of TimeSpan is used, which does not represent full
time interval. Possibly 'TotalSeconds' value was intended instead. AssetUploader.cs 182
Orchard CMS
should be
TotalSeconds
14. A Few Examples: Sorting
PVS-Studio: V3078 Original sorting order will be lost after repetitive call to 'OrderBy' method.
Use 'ThenBy' method to preserve the original sorting. CodeCoverageMethodElement.cs 124
SharpDevelop
void Init()
{
....
this.SequencePoints.OrderBy(item => item.Line)
.OrderBy(item => item.Column);
}
15. A Few Examples: A Tricky Detail
• The analyzer can recognize bug patterns your team don’t even know
of.
static class Profiler
{
[ThreadStatic]
private static Stopwatch timer = new Stopwatch();
....
Mono
V3089 Initializer of a field marked by [ThreadStatic] attribute will be called once on the first
accessing thread. The field will have default value on different threads. System.Data.Linq-
net_4_x Profiler.cs 16
17. The Biggest Mistake Made When Using Static
Analyzers
• One-time checks have little effect
• Think of it by analogy with compiler warnings
• Everything really bad has been already fixed using other means;
you have only minor defects and heisenbugs left
18. False Positives
• These are an unavoidable evil, but static analyzers provide various
means to tackle them
• Means of dealing with false positives in PVS-Studio
• selective warning suppression
• selective exclusion of folders/files from analysis
• selective disabling of diagnostics
• suppression markup base, which is the most important
feature – more on this in the next slides
19. PVS-Studio. The Idea Behind the Suppression
Markup Base
• Allows you to start using the analyzer immediately on newly written
or modified code
• Old bugs are unlikely to be critical, so you could get back to them
later when you have time for that
20. Getting Started with the Suppression Base
1. Check the project
2. Mark all the warnings produced by the analyzer as irrelevant
3. Submit the file with the base to the version control system
4. PROFIT
21. A Bit More About PVS-Studio
• You can set PVS-Studio to launch on the server
• And use the BlameNotifier utility to send emails to those developers
who submitted faulty code
22. Why So Much Talk About Regular Use?
• Here’s a comment by a PVS-Studio user: "A User's Experience of
Working with the Analyzer" - https://www.viva64.com/en/b/0221/
The conclusion is: the bug we had wasted about 50 hours to track was
detected at once with the first run of the analyzer and fixed in less
than an hour!
Alexander Lotokhov
23. SonarQube: Data Visualization
• Open-source platform for continuous inspection of code quality
• Comes with a number of analyzers, including Sonar C#
• Nice visualization
25. SonarQube: Integration with Third-Party
Analyzers. What For?
• The strong point of Sonar C# is measuring the code quality (detection
of "code smells")
• The weak point of Sonar C# is that it offers too few diagnostics to
detect bugs leading to incorrect program operation
26. SonarQube: Integration with Third-Party
Analyzers
• A way out: integration with other analyzers
• Such as PVS-Studio
• PVS-Studio is especially good at detecting real bugs and typos
• 137 diagnostics to detect bugs in C# code
Example: Analysis of PascalABC.NET using SonarQube plugins: SonarC#
and PVS-Studio - https://www.viva64.com/en/b/0492/
28. The Second Biggest Mistake
• Myth: static analyzers are tools for beginner programmers!
• Myth: we are pros and we never mistype!
• We all make mistakes. What’s more, we are prone to making mistakes
in certain situations.
• Here’s an article by Andrey Karpov to illustrate this:
The Evil within the Comparison Functions
29. No Aliens to Blame
IronPython and IronRuby
public static int Compare(SourceLocation left,
SourceLocation right) {
if (left < right) return -1;
if (right > left) return 1;
return 0;
}
PVS-Studio warning (C#): V3021 There are two 'if' statements with identical conditional
expressions. The first 'if' statement contains method return. This means that the second 'if'
statement is senseless. SourceLocation.cs 156
30. The Evil Within the Comparison Functions
SharpDevelop
public int Compare(SharpTreeNode x, SharpTreeNode y)
{
....
if (typeNameComparison == 0) {
if (x.Text.ToString().Length < y.Text.ToString().Length)
return -1;
if (x.Text.ToString().Length < y.Text.ToString().Length)
return 1;
PVS-Studio warning: V3021 There are two 'if' statements with identical conditional
expressions. The first 'if' statement contains method return. This means that the second 'if'
statement is senseless NamespaceTreeNode.cs 87
31. The Evil Within the Comparison Functions
public int Compare(GlyphRun a, GlyphRun b)
{
....
if (aPoint.Y > bPoint.Y)
{
return -1;
}
else if (aPoint.Y > bPoint.Y)
{
result = 1;
}
else if (aPoint.X < bPoint.X)
....
WPF samples by Microsoft
PVS-Studio warning: V3003 The use of 'if (A)
{...} else if (A) {...}' pattern was detected.
There is a probability of logical error presence.
Check lines: 418, 422. txtserializerwriter.cs
418
32. The Evil Within the Comparison Functions
• Link to the article:
https://www.viva64.com/en/b/0509/
33. Conclusions:
• Static analysis is a means to find a portion of bugs right away before
they get expensive
• Static analysis must be used on a regular basis
• You can start using it right away, putting the old bugs aside to deal
with them later
• C#-programmers may want to check out SonarQube (Sonar С#) and
PVS-Studio
34. Useful Links
• List of tools for static code analysis
https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis
• PVS-Studio
https://www.viva64.com/en/pvs-studio/
• SonaqQube
https://www.sonarqube.org/
36. More Examples if There’s Time Left
Umbraco
protected virtual void OnBeforeNodeRender(ref XmlTree sender,
ref XmlTreeNode node,
EventArgs e)
{
if (node != null && node != null)
{
if (BeforeNodeRender != null)
BeforeNodeRender(ref sender, ref node, e);
}
}
PVS-Studio: V3001 There are identical sub-expressions 'node != null' to the left and to the
right of the '&&' operator.
37. More Examples if There’s Time Left
CodeContracts
if (mTypeConstraint == TypeConstraint.CLASS)
{
oh.Output("class", false); comma = true;
}
else if (mTypeConstraint == TypeConstraint.STRUCT)
.....
else if (mTypeConstraint == TypeConstraint.CLASS)
{
oh.Output(mClassConstraint, false); comma = true;
}
PVS-Studio: V3003 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a
probability of logical error presence.
38. More Examples if There’s Time Left
CodeContracts
for (int i = 0; i < data.Length; i++)
{
if (data[i] != null)
{
for (int j = 0; j < lastElement[i]; i++)
{
str.AppendFormat("({0},{1})",
data[i][j].Index, data[i][j].Value);
}
}
}
PVS-Studio: V3014 It is likely that a wrong variable is being incremented inside the 'for'
operator. Consider reviewing 'i'.
39. More Examples if There’s Time Left
Orleans
public static string SanitizeTableProperty(string key)
{
key.Replace('/', '_'); // Forward slash
key.Replace('', '_'); // Backslash
key.Replace('#', '_'); // Pound sign
key.Replace('?', '_'); // Question mark
....
return key;
}
PVS-Studio: V3010 The return value of function 'Replace' is required to be utilized.
40. More Examples if There’s Time Left
SharpDevelop
public WhitespaceNode(string whiteSpaceText,
TextLocation startLocation)
{
this.WhiteSpaceText = WhiteSpaceText;
this.startLocation = startLocation;
}
PVS-Studio: V3005 The 'this.WhiteSpaceText' variable is assigned to itself.
www.viva64.com40
41. More Examples if There’s Time Left
SharpDevelop
ContentPropertyNode clickedNode =
clickedButton.DataContext as ContentPropertyNode;
clickedNode = clickedButton.DataContext as ContentPropertyNode;
if (clickedNode == null)
Redundant code.
PVS-Studio: V3008 The 'clickedNode' variable is assigned values twice successively.
Perhaps this is a mistake.
42. More Examples if There’s Time Left
SharpDevelop
public override string ToString()
{
return
String.Format("[Line {0}:{1,2}-{3,4}:{5}]",
File, Row, Column, EndRow, EndColumn, Offset);
}
PVS-Studio: V3025 Incorrect format. A different number of actual arguments is expected
while calling 'Format' function. Expected: 4. Present: 6.
43. More Examples if There’s Time Left
GitExtensions
if (string.IsNullOrEmpty(translationCategory.Name))
new InvalidOperationException(
"Cannot add translationCategory without name");
PVS-Studio: V3006 The object was created but it is not being used. The 'throw' keyword
could be missing: throw new InvalidOperationException(FOO).
throw
44. More Examples if There’s Time Left
Orleans
if (numRemoved > 0)
if (logger.IsVerbose) logger.Verbose(....);
else
if (logger.IsVerbose2) logger.Verbose2(....);
PVS-Studio: V3033 It is possible that this 'else' branch must apply to the previous 'if'
statement. Interner.cs 274
45. MSBuild (ResolveSDKReference_Tests.cs)
installedSDK.SetMetadata("SDKName", "GoodTestSDK, Version=2.0");
t.InstalledSDKs = new ITaskItem[] { installedSDK };
t.TargetedSDKConfiguration = "Debug";
t.TargetedSDKConfiguration = "x86";
t.BuildEngine = engine;
PVS-Studio: V3008 The 't.TargetedSDKConfiguration' variable is assigned values twice
successively. Perhaps this is a mistake.
t.TargetedSDKArchitecture
• A nice example of how static analysis complements unit testing
More Examples if There’s Time Left
46. More Examples if There’s Time Left
CruiseControl.NET
public void ModificationsAreComparedByModifiedDatetime()
{
Modification alpha = new Modification();
alpha.ModifiedTime = new DateTime(1975, 3, 3);
Modification beta = new Modification();
alpha.ModifiedTime = new DateTime(1961, 3, 3);
....
}
PVS-Studio: V3008 The 'alpha.ModifiedTime' variable is assigned values twice
successively. Perhaps this is a mistake.
47. Xamarin.Forms (C#)
internal bool IsDefault
{
get { return Left == 0 && Top == 0 &&
Right == 0 && Left == 0; }
}
V3001 There are identical sub-expressions 'Left == 0' to the left and to the right of the '&&'
operator. Thickness.cs 29
More Examples if There’s Time Left
48. Space Engineers (C#)
void DeserializeV0(XmlReader reader)
{
....
if (property.Name == "Rotation" ||
property.Name == "AxisScale" ||
property.Name == "AxisScale")
continue;
....
}
More Examples if There’s Time Left
V3001 There are identical sub-expressions 'property.Name == "AxisScale"' to the left and to
the right of the '||' operator. Sandbox.Graphics MyParticleEmitter.cs 352
49. A lot more examples:
https://www.viva64.com/en/examples/