Compiler warnings, Coding standards, Code quality…oh my! (Part 2)

on Nov 3, 09 • by Alen Zukich • with No Comments

In the first blog series, we discussed the value of compiler warnings and wondered why a static analysis tool would have similar error checking features. In this installment, we want to dive deeper into this question by reviewing errors that can be found by compilers, why they matter, and what limitations compilers...

Home » Coding Standards » Compiler warnings, Coding standards, Code quality…oh my! (Part 2)

In the first blog series, we discussed the value of compiler warnings and wondered why a static analysis tool would have similar error checking features. In this installment, we want to dive deeper into this question by reviewing errors that can be found by compilers, why they matter, and what limitations compilers have in this area.

Let’s take an example of the “implicit int” rule:

int foo() {
   const x = 0;
   return x;
}

This is a situation where failure to specify a type results in this compiler warning from (gcc v.3.4.4) or Microsoft cl (v.14):

gcc -Wall -c main.c
main.c: In function `foo':
main.c:2: warning: type defaults to `int' in declaration of `x'

cl -c -Wall main.c
main.c(2) : warning C4431: missing type specifier - int assumed. Note: C no longer 
supports default-int

You can’t rely on the standard C/C++ implementations to support the implicit int anymore and these compilers alert you to that.  I do have to say, I’ve never seen anyone do this in practice, but it’s nice to know it’s there.

Let’s look at another example:

void foo() {
   if (sizeof(char) < 2)  // defect - the condition is constant
   {
      /* ... */
   }
}

The issue above is that the condition is constant.  See the C99 standard for details on this (section 6.6).  If we run the cl compiler we get:

cl -c -Wall main2.c
main2.c(2) : warning C4127: conditional expression is constant

Here, the cl compiler finds the issue, gcc does not (well, at least my version).   Okay, interesting let’s take a look at a C++ example:

class A
{
   public:
   // non-virtual destructor
   ~A();
   virtual void f1();
};

With this example, if you run either gcc or cl you get the same thing:

gcc -Wall -c main3a.cpp
main3a.cpp:2: warning: `class A' has virtual functions but non-virtual destructor

cl -c -Wall main3a.cpp
main3a.cpp(7) : warning C4265: 'A' : class has virtual functions, but destructor is
not virtual instances of this class may not be destructed correctly

According to the output from both compilers, we made a boneheaded mistake and forgot to assign the destructor as virtual.  Let’s go one step further and define a new method:

void deleteA(A *a) {
   delete a;
}

This method adds a new level of complexity.  When an object of a class derived from the given one is deleted through a pointer to the given class, the destructor of the derived class is not executed, and members of the derived class are not disposed of properly.  In this case, you will not get any warnings from any compiler.  The difference here is that compilers only work within the context of the file/function.  In this case, you are out of luck with compilers, but luckily source code analysis excels in this.

So, the message here is that compiler warnings are quite useful, but they do have their limitations.  Not all compilers report the same things consistently, nor do they cover analysis beyond a single function or file.  Still, make sure you run the compiler warnings, then implement static source code analysis as part of your process to go deeper and find some more complex issues in your code.

For the next blog of this series I’ll cover coding standards and where they fit in your code quality process.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Scroll to top