The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,676 other followers

Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been initialized”…

Posted by jpluimers on 2019/01/21

Historically, [WayBack] W1036: Variable '%s' might not have been initialized (Delphi) has had a lot of gotchas.

The most important still is that it never show for managed types (strings, interfaces, etc).

Usually W1036 shows for non-managed types, but Dan Hacker has found a new case where it does not in [WayBack] Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been initialized’ if the StringsToDo parameter in DoSomething is defined as a var… – Dan Hacker – Google+

He noticed it in Delphi XE and 10.2 Tokyo.

I tested it with the Win32 compiler in XE8.

This warns:

program W1036;
{$APPTYPE CONSOLE}
uses
  System.SysUtils,
  System.Classes;

procedure DoSomething(var StringsToDo: TStringList); // <-------- this line makes the difference
begin
  //do nothing
end;

procedure Test;
var
  MyStrings : TStringList;
begin
  MyStrings.Free;   {W1036 warning if StringsToDo param is NOT var}
  DoSomething(MyStrings);
end;

begin
end.

This does not warn:

program W1036;
{$APPTYPE CONSOLE}
uses
  System.SysUtils,
  System.Classes;

procedure DoSomething(StringsToDo: TStringList); // <-------- this line makes the difference
begin
  //do nothing
end;

procedure Test;
var
  MyStrings : TStringList;
begin
  MyStrings.Free;   {W1036 warning if StringsToDo param is NOT var}
  DoSomething(MyStrings);
end;

begin
end.

initially, I misread his report and reacted wrongly on the cause (but rightly on the suggested use case of var and of TStringList):

Because a var parameter means that the caller should pass in an initialised parameter. Otherwise it should be an out parameter, not a var parameter.

var parameter for reference types like TStrings (only pass as TStringList if it deliberately is not compatible with TStrings) is a risky thing anyway, because the called method can overwrite it and then the caller has to notice the change, then decide what to do with the previous value (likely free it).

I later correct myself:

Looking better, I think it is a compiler issue.

The only difference between nothing and var is the loading of the parameter as a pointer:

with var

//W1036.dpr.16: MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
//004CD924 8B45FC mov eax,[ebp-$04]
//004CD927 E8B8A6F3FF call TObject.Free
//Project1.dpr.17: DoSomething(MyStrings);
//004CD92C 8D45FC lea eax,[ebp-$04]
//004CD92F E8E0FFFFFF call DoSomething
without var
//W1036.dpr.16: MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
//004CD924 8B45FC mov eax,[ebp-$04]
//004CD927 E8B8A6F3FF call TObject.Free
//Project1.dpr.17: DoSomething(MyStrings);
//004CD92C 8B45FC mov eax,[ebp-$04]
//004CD92F E8E0FFFFFF call DoSomething

So:

  • with a var, a pointer to the instance of MyStrings (obtained by a lea instruction) gets pushed on the stack
  • without a var, the instance of MyStrings (obtained by a mov instruction) gets pushed on the stack.

For the difference metween mov and lea, and the use of [] brackets, see:

–jeroen

Source: Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been i…

PS: after a discussion with Rudy Velthuis, trying to explain the [WayBack] Outside-In vs. Inside-Out Thinking | CustomerThink on the general managed versus non-managed behaviour of W1036, I have come up with this comment and the solution:

+Rudy Velthuis designing a warning thinking from the compiler to the programmer instead of thinking from the programmer to the compiler.

The documentation on the warning never mentions it will not show for certain areas of types, so the programmer will think it always works.

From a compiler perspective, it is very clear it will not work, but from a programmer perspective, you have to know (and constantly remember) the cases it won’t. Computer programs are much better capable of “remembering” those cases, so it is their task to do that, not the programmer’s task.

A solution could be to have two hints for uninitialised variables: one for variables of unmanaged types (which will get random values when living on the stack) and one for variables of managed types (which will get default values).

3 Responses to “Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been initialized”…”

  1. rvelthuis said

    But it should not show! The string is already initilaized, so showing it would be wrong.

    The expectation that it should show at all is wrong, not the compiler. You don’t have to remember the cases when it won’t show. If it doesn’t show, there is nothing to show, period.

    That is not a “customer-think vs. compiler-think” issue, nor is it an issue of “not showing for certain types”, it is simply a matter of not showing a hint that is wrong.

    • jpluimers said

      And this perfectly describes the inside-out versus outside-in thinking.

      Every time people that bump into this issue ask me why this is not shown for managed types, they have the expectation the warning will show for variables that have not been initialised by the programmer.

      That point of view makes perfect sense for an outside-in perspective.

      • rvelthuis said

        I don’t think it does.

        I am on the outside (I am a user of the compiler) and don’t want a warning or hint when there is nothing to hint about. A compiler cannot and should not hint just because there are false expectations. I, an outsider, want the compiler to act sensibly, not apologetically. It is a tool, and I expect it to behave like one, not like a psychiater or a mindreader. So no, that is not inside-out thinking, that is my expectationm that tool behjaves like one and only issue an error/warning/hint when there actually is som,ethjing to hint about.

        So tell those who complain about the lack of a hint that there is nothing to hint about because the string is already initialized. I don’t wan the compiler to tell the user something like “hey, you may not have changed the value of the string”, because that is up to the user. It would extremely annoy me and anyone who doesn’t want to change it unless some conditions apply. In other words: no hints where no hints are due. No false positives.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: