Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing warning about variable might not have initialized

I have a bug in my code. There's no doubt about it; it's my bug and entirely my fault:

procedure TfrmCageSetup.actDeleteFloatExecute(Sender: TObject);
var
   conn: TADOConnection;
begin
   ...
   if not float.CanDelete(conn, {out}noDeleteReason) then
   begin
   ...
end;

I forgot to initialize the variable conn. As a result, it is stack junk. And when the target callee checks the argument, it passes:

function TFloat.CanDelete(Connection: TADOConnection; out NoDeleteReason: string): Boolean;
begin
   if Connection = nil then
      raise EArgumentNullException.Create('Connection');

And i had a very strange access violation sometimes.

But why didn't Delphi catch it?

Yes it's my fault. But part of the reason i use a statically, strongly, typed language, is so that is can help me catch these stupid mistakes.

First i checked that i wasn't actually initializing it to some damage or destroyed object (perhaps it was initialized - just badly). But no, it really is uninitialized between declaration and first use:

enter image description here

Then i thought that perhaps i had turned off the warning:

Variable might not have been initialized

But no, it is enabled (globally, and for my platform, as for my release type):

enter image description here

So then i built it again (even though this bug has been in the code for months), to make sure i didn't miss the error. But no; aside from some bugs in the VCL and JVCL, Delphi isn't catching the error:

enter image description here

I want Delphi to help me

What can account for this?

I want to know if there's any other places in my code that have this same, awful, horrible, completely detectable, bug.

Perhaps it's the 64-bit compiler. There are grumblings that the 64-bit back-end (being all new) isn't as intelligent as the 32-bit backend. What if i try changing it to 32-bit?

Still no:

enter image description here

Same with 32-bit release and 64-bit release.

1/25/2015 - Does it even show such a warning?

Steps to reproduce the warning does show:

procedure TForm1.FormCreate(Sender: TObject);
var
    silverWarrior: Integer;
begin
    IsWrong(silverWarrior);
end;

function TForm1.IsWrong(n: Integer): Boolean;
begin
    Result := True;
end;

Gives warning:

W1036 Variable 'silverWarrior' might not have been initialized

enter image description here

You don't even have to be passing the value to another function; simply using an uninitialized variable gives the warning (depending on the mood of the compiler that particular day):

procedure TForm1.FormCreate(Sender: TObject);
var
   silverWarrior: Integer;
   theAnswer: Integer;
begin
   theAnswer := silverWarrior + 42;
end;

gives a warning:

W1036 Variable 'silverWarrior' might not have been initialized

More than 32 local variables causes failure?

No; you still get the warning:

procedure TForm1.FormCreate(Sender: TObject);
var
    localVariable1: Integer;
    localVariable2: Integer;
    localVariable3: Integer;
    localVariable4: Integer;
    localVariable5: Integer;
    localVariable6: Integer;
    localVariable7: Integer;
    localVariable8: Integer;
    localVariable9: Integer;
    localVariable10: Integer;
    localVariable11: Integer;
    localVariable12: Integer;
    localVariable13: Integer;
    localVariable14: Integer;
    localVariable15: Integer;
    localVariable16: Integer;
    localVariable17: Integer;
    localVariable18: Integer;
    localVariable19: Integer;
    localVariable20: Integer;
    localVariable21: Integer;
    localVariable22: Integer;
    localVariable23: Integer;
    localVariable24: Integer;
    localVariable25: Integer;
    localVariable26: Integer;
    localVariable27: Integer;
    localVariable28: Integer;
    localVariable29: Integer;
    localVariable30: Integer;
    localVariable31: Integer;
    localVariable32: Integer;
    localVariable33: Integer;
    localVariable34: Integer;
    localVariable35: Integer;
    localVariable36: Integer;
    localVariable37: Integer;
    localVariable38: Integer;
    localVariable39: Integer;
    localVariable40: Integer;
    localVariable41: Integer;
    localVariable42: Integer;
    localVariable43: Integer;
    localVariable44: Integer;
    localVariable45: Integer;
    localVariable46: Integer;
    localVariable47: Integer;
    localVariable48: Integer;
    localVariable49: Integer;
    silverWarrior: Integer;
    theAnswer: Integer;
begin
    theAnswer := silverWarrior + 42;
end;

W1036 Variable 'silverWarrior' might not have been initialized

like image 651
Ian Boyd Avatar asked Feb 12 '23 02:02

Ian Boyd


1 Answers

That's just how it is. The compiler isn't perfect at spotting such errors. As well as your problem (uninitialized variable that the compiler fails to warn about), it is quite possible to encounter an initialized variable that the compiler does warn about. And to compound the misery, it is possible to have code which the 32 bit compiler emits a warning, but the 64 bit compiler does not. And vice versa, sometimes the 64 bit compiler warns, and the 32 bit compiler does not.

I've not found any pattern to this. I have no solution. I have an inkling that control statements like break and exit could be associated with these problems, but I've got no hard proof that is so.

Only Embarcadero can solve this so the best that you can do is submit a bug report and hope that somebody at Embarcadero cares.

like image 97
David Heffernan Avatar answered Mar 17 '23 06:03

David Heffernan