Check your compiler warnings and hints. They may still be errors.

I try to follow a zero hints and warnings policy for my code. (I admit I don’t always succeed though. 😉 ) But I was initially confused on how to solve this, and because of that learned something about not always following directions blindly…

See this example code.

function Test: boolean;
var Something: TSomething;
begin
  Result := false;
  Something := TSomething.Create;
  try
    // Perform something that may raise an exception
    Result := true;
  finally
    FreeAndNil (Something);
  end;
end;

This function should return true if everything went ok, without exceptions, and false otherwise. You’ve probably at some point written something like that too. However, I get a compiler hint pointing to the first line of the function:

[dcc32] H2077 Value assigned to 'Test' never used.

I can make the hint go away by removing the first Result := false assignment. However, is my Result then guaranteed to initialize to false, as I would like it to?

Well, I make a habit of initializing my local variables and according to this StackOverflow answer, I am correct in doing so:

“For local variables and anything related to stack, it will contain garbage, so you’re responsible to provide a meaningful value before using the variables.”

Is the Result special variable an exception to this? I already found that Result is not initialized if it returns a string, but what about returning a boolean or an integer?

Well… the answer is a very subtle one. Result is not an exception and should still be initialized! But, then why is the compiler hinting at me for doing so? Should I ignore the hint? (Yikes, start making exceptions on my zero-tolerance policy?) No, in fact, the hint is still correct. It is because the assignment really is unused. My function has a bug: it does in fact not return true when successful and false otherwise — it will return true when successful and raise an exception otherwise. It will indeed never return false. Notice that I was only using try…finally and not catching the exception. An exception would have escaped the function to the caller. The compiler is smart enough to notice this potential code path: if you, for the sake of this demonstration, replace finally with except, and the hint goes away.

So I should either

  • Remove the Result := false; assignment. The hint then goes away but all the code calling this function should be checked and/or modified to assume an exception if something goes wrong instead of a false return value. I could (should?) even make it a procedure instead of a function, since the return value now does no longer matter.
  • Add exception handling code by means of an additional try..except construct, to make sure the function actually returns false if an exception occurs, as it was intended to.

Bottom line: always check up on compiler warnings and even hints. They may not be errors but very well still point to an error in your code! This could have made a really nasty bug to find, if something had actually gone wrong in that piece of code.

(And perhaps bottom line #2: Always initialize your variables. Even if you think the compiler hints you not to.)

Advertenties

Over Shiftkey
I am Maarten, owner of and chief software developer for Shiftkey software development from The Netherlands. I will be writing mainly about things I run into when programming in C# or Delphi.

Geef een reactie

Vul je gegevens in of klik op een icoon om in te loggen.

WordPress.com logo

Je reageert onder je WordPress.com account. Log uit / Bijwerken )

Twitter-afbeelding

Je reageert onder je Twitter account. Log uit / Bijwerken )

Facebook foto

Je reageert onder je Facebook account. Log uit / Bijwerken )

Google+ photo

Je reageert onder je Google+ account. Log uit / Bijwerken )

Verbinden met %s

%d bloggers liken dit: