Delphi variable might not have been initialized warning
Asked Answered
S

1

11

I've added some code to my delphi project to interact with the registry, using some tutorials I found online to guide my effort. Every example I've seen seems to use this structure for their registry access:

var
  Registry: TRegistry;
begin
  try
    Registry := TRegistry.Create;
    //additional code to access and use the registry object could go here
  finally
    Registry.Free;
end;

But when I implement my code following that structure, I am getting a warning that my variable Registry may not have been initialized on the line where I free the TRegistry object.

So, I'm wondering whether the examples I've found are just wrong on the right way to access the registry. Should I be calling Free on my TRegistry object regardless of whether the Create succeeeds, and just ignore the warning? Should, instead, my try/finally block only surround the code after the successful constructor call, but not wrap the create call? Something else?

Scissor answered 17/3, 2012 at 17:46 Comment(0)
R
24

In your code, if TRegistry.Create raises an exception then the Registry variable will not be assigned. And thus the finally will attempt to access an uninitialized variable.

The correct way to write the code is to make sure that the variable is assigned before you enter the try/finally block.

Registry := TRegistry.Create;
try
  //additional code to access and use the registry object could go here
finally
  Registry.Free;
end;

This is the most fundamental lifetime management pattern in Delphi coding and you should commit it deeply to muscle memory.

Note that if the constructor fails, then it will tidy up the partially constructed object before propagating the exception. The new object reference, Registry in this code, is only assigned if the constructor completes successfully.

I would hope that the examples you found were in fact written as per my code above and you somehow transcribed them incorrectly. If they are written as per the question, then they are clearly in error.

Raddled answered 17/3, 2012 at 17:49 Comment(19)
do I need to do any additional checking after Create before the try block to actually make sure Registry initialized ok?Scissor
And just for example, planet-source-code.com/vb/scripts/… would be one of the sort of tutorials I found that is indeed it appears erroneous, hence the question to try and understand whether that code actually resembles what a more advanced delphi developer would do or not.Scissor
Clearly you need to find better sources than that site!Raddled
@JessicaBrown, it that URL VB part is like big red sign, which reads CAUTION, WTF AHEAD :-) Truth is, failed constructor will cause instance to be Destroyed and will return nilNode
@user Minor correction. When the constructor fails it returns nothing and the exception propagates past the assignment to the instance reference.Raddled
@DavidHeffernan, yeah, thats better, or i think its even better will be to replace "returns nothing" -> "never returns"Node
@user yes, never returns is perfectRaddled
True true, thank you for helping me learn to write better delphi code! I've been to a pile of bookstores and libraries and not one of them has a single book about any version of Delphi, so I've been relying on online resources for now to bring myself up to speed on Delphi until I can get a good reference book in my hands.Scissor
It's totally fine to call Free on a null reference. docwiki.embarcadero.com/Libraries/Rio/en/System.TObject.FreeFruma
@Fruma How does that comment relate to the question?Raddled
@DavidHeffernan The warning is bogus in the case of Free. There is nothing erroneous about the code in the question. It's not necessary to make sure the variable is assigned to before calling Free on it. It is of course necessary if you're going to do anything else with it.Fruma
@Hamsh Wrong. The code is bogus because an uninitialized variable has indeterminate value. Calling Free on nil is fine, but that variable is not guaranteed to be nil in case the constructor raises an exception.Raddled
@DavidHeffernan I'm intrigued. In the case the constructor raises an exception, what could the variable be set to? Please can you provide an example in which the variable is not nill? Thanks!Fruma
@hamish It's not set to anything. If the exception is raised then the assignment does not happen and the variable remains uninitialized. No example necessary beyond that in the question. You want a simple example, make a procedure with a local variable. Don't initialize it. See what value it has.Raddled
@DavidHeffernan It's nill.Fruma
@Fruma Guess you got unlucky then. Try this program for size: program Project69; {$APPTYPE CONSOLE} procedure Foo1; var i: Integer; begin i := 42; end; procedure Foo2; var i: Integer; begin Writeln(i); end; begin Foo1; Foo2; Readln; end.Raddled
Ok I'm seeing different behaviour in a new program vs the program I had stuck a test in. I'll investigate! Thanks for persisting :)Fruma
Nothing to investigate. It's what I said. Uninitialized variables are, er, well, not initialized. Their initial values are undefined.Raddled
#7644153Fruma

© 2022 - 2024 — McMap. All rights reserved.