Tuesday, May 27, 2014

C++: Testing for NULL

Like any good developer I'm constantly learning more about the programming language I work in (C++).  But several of the things I've learned lately have gone against years of working the opposite.

Take for example the following code:

CStudent *pStudent = new CStudent(nStudendId);
if(pStudent)
{
    pStudent->DoSomething();
}


This is a very typical snippet of code.  What's of interest here is the test if pStudent is NULL after the allocation.  If the allocation fails then pStudent would be NULL, and you want to test NULL pointers before dereferencing them which would result in an application crash.  I used to believe that programmers that didn't test the pointer first we being "lazy."  Well, it turns out testing the return value is not only unnecessary, it's actually wasted CPU cycles - so in other words it's bad to test the return from a performance reason.  At the heart of the matter here is the C++ operator 'new.'  If new is unable to allocate the requested block of memory, new throws an exception.  So in the above code, it's impossible for pStudent to ever be NULL.  It will either be a valid block of memory, or an exception will be thrown.

Knowing this is kind of nice.  Code is usually cleaner and easier to read without all these tests against NULL after calling 'new.'  Now let me be clear, this is only when calling 'new.'  Other allocaters such malloc do NOT throw an exception.  So it's still a good idea to test their return.


Related to this, it turns out it's also pointless to test the pointer before freeing the memory.

if(pStudent)
    delete pStudent;

This is a pointless test because 'delete' checks the pointer before proceeding.  So testing the pointer first is again wasted CPU cycles.

Unlike malloc, the same thing is true with 'free.'  The function 'free()' tests the pointer, so there is no need to test before calling free().  But this is not true of all functions that cleanup resources.  The Windows API CloseHandle() does not check, so as the developer it's your job to test before calling CloseHandle().


Thursday, May 22, 2014

Static Code Analyzers

Recently at work I tried a class of software I've never used before, something called "static code analyzers."  Basically it is software that scans your source code and looks for bugs and optimizations.  They call them "static" because they only analyze the source code, there is a separate class of tools to analyze your program at runtime.  Anyway, I've never used this type of software before and I tried a number of different tools so I thought I'd comment about each tool I used.

Before I talk about each tool, I'll say that I work with the language of C++ using the Microsoft Visual Studio compiler.  So the tools I tried were all geared towards that environment.   Also, it is true that because of the rules and structure of newer languages (Java, C#, etc.) that tools like this are most useful in C++.  However; any language it's entirely possible to make a mistake in code that is perfectly valid syntactically (so the compiler/interpretor won't catch it) but yet it is still a bug.   That is the goal of these static code analyzers.   A tool to help the developer catch his own mistakes.  If the compiler is like a spell-checker, then a code analyzer is like a grammar-checker.



CppCheck: The first tool I tried is called CppCheck, which is a free open-source project.  This tool ended up being the easiest tool to run.  What I liked about this tool was you merely give it a directory (and optionally some additional Include folders) and it analyzes all the source code in that folder.  It had a clean simple UI.  Incredibly easy, and the results were pretty good too!


PVS-Studio:  PVS-Studio is a commercial product, but does offer a free trial version.  I was hesitant to try a commercial product mainly because lately I've been using a lot of free and open-source software.  But I was very pleased with PVS-Studio.  It operates a little differently than CppCheck.  PVS-Studio integrates with Visual Studio, after a successful build PVS-Studio automatically starts and analyzes the code that was used during that build.  PVS-Studio also has a second standalone mode of operation.  You run the tool, then compile your code using the compiler of your choice, after which it analyzes the source.  Where PVS-Studio shined was in its results.  It's was pretty quick to analyze, much quicker than CppCheck on the same code.  Also, the way in which it filters and displays the issues it finds makes navigating and fixing the results very easy.  The downside is this is commercial software.  I would actually consider buying PVS-Studio for my own personal use, but I don't like their licensing model.  It's clearly geared towards corporations and large development teams.  They also sell the product on, what I would call, a subscription model.  You buy a license for a year, and after that year if you still want to use the product you must license it again.  I hate this type of licensing.  If I buy the product, I want to be able to use it indefinitely.


Eclipse C++ IDE w/ CDT-CODAN:  I read that the Eclipse IDE includes a module called "CODAN" for code analysis.  CODAN is a portmanteau for CODe ANalysis.  Since Eclipse is free I thought I'd give it a try.  I have never really used the Eclipse IDE before so there was a bit of a learning curve to get my source code from Visual Studio into an Eclipse project.  I didn't care if the code compiled, in fact I knew it wouldn't because it's MFC-based code and the compiler Eclipse uses (MinGW) doesn't handle MFC.  I just wanted to be able to run the code analyzer against my code.  After several hours of trying I got the code in and was able to run the analyzer.  My results with CODAN were mixed.  The problem I had was the vast majority of my code, the code analyzer had a problem with.  This was due to the undefined Windows symbols throughout my code.  Even though I pointed the compiler at the appropriate Windows SDK Include folders, it still could not resolve the symbols.  I'm sure the problem is my lack of experience with Eclipse and knowing how to configure it.  Now all of that said, CODAN still was able to find a number of problems in my code which no other tool found.  So it was worth while, I just wish I was able to analyze more of my code with this tool.


Visual Studio:  Starting in Visual Studio 2005 Microsoft includes a code analysis tool of their own.  So the good news is it's free (more on that later), and it's already integrated with Visual Studio.  All you have to do is go into your project settings and enable C/C++ code analysis.  When you run your next compilation it will report the issues it finds.  Unfortunately, this tool is not available with every version of Visual Studio.  The Express, Academic, and Professional versions do not include it.  Only the top-of-the-line "Team" version includes this tool.  So there's a good chance you don't have access to it.  But if you do, it's there so use it.  For me, this tool didn't find as many issues as I was hoping.  It did find some, but I was hoping for more.  Of course, I had already used the above 3 tools so there were fewer issues to find at that point.


PreFast:  Turns out there is another free tool from Microsoft called PreFast.  This tool is included for free in the Windows DDK (driver development kit).  It's designed to analyze driver source code, but I read on the Internet that it can be used to analyze user-mode code as well.  I didn't actually run my source code through PreFast.  I may go back and do so in the future.


Your Compiler:  As it turns out, you probably have a free simple code analyzer already on your system - your compiler.  Most compilers have different warning levels, but may default to a lower setting.  Visual Studio has 4 levels but defaults to 3.  If you turn the warning level up and recompile you'll get a lot of extra warnings.  The quality of these warnings won't be as good as the above dedicated tools, but there is still a good chance you'll find at least one issue using this free technique.


CppDepend:  CppDepend is another commercial product that I read great things about on the Internet, and they offer a free trial, so I decided to give it a try.  However; I didn't go very far with this tool.  Right out of the gates it wouldn't run because it required the .NET runtime which wasn't installed on my system.  It also turns out this tool does not support my version of Visual Studio.  So in the end I was never able to get this tool to run.



So there's my review of several static code analyzers.  To be honest, I wasn't expecting much going in.  When I write code, I'm very attention-to-detail oriented.  You could even say "anal" although I prefer "fastidious."  So I wasn't expecting much from these tools.  I was surprised by the number of "issues" it found.  I would definitely use them again in the future, and recommend others use them as well.  If you're trying to decide which tool to use - don't choose, use them all.  Run your source code through multiple tools to get even more results.  It's not like you're cheating on your spouse, there is no harm in using multiple tools and only gains if you do.  Happy coding!