Ruslan 6 Posted March 5, 2019 I use a lot of class/pointer variables (e.g. aItem := TItem.Create; or as iterations in Dictionary or ObjectLists) inside methods as local and temporary variables, at the end of each method I used to write "aItem := nil;" if no longer need that. In building the application I see a lot of "H2077 Value assigned to 'aItem' never used". Also in some functions I used to write the default Boolean Result value at the beginning as "False", and the builder show in messages "H2077 Value assigned to <function> never used". What is the right way of freeing the local class variables (without loosing the data) and default function result values? Share this post Link to post
ByteJuggler 45 Posted March 5, 2019 (edited) Normal Delphi objects, using the Windows compiler, does NOT have garbage collection or any kind of automatic memory management like Java, C# etc. This means if you merely assign "nil" to an object reference, the memory pointed to originally by that reference is still allocated in the heap somewhere, but now "lost" -- you've caused a memory leak(!). Normal objects should be disposed of by calling the destructor, e.g. var LMyLocalObj : TSomeClass; begin LMyLocalObj := TSomeClass.Create(...); try //do something with LMyLocalObj finally LMyLocalObj.Free; //or if you prefer FreeAndNil(LMyLocalObj); end; // more code perhaps... end; Setting the reference to nil is a safeguard since if you do not do this then the value of the object reference will point to where the now-freed object used to be. For a while this may still look valid if accidentally used/derefenced, whereas if you reset the reference variable to nil then trying to dereference it will cause an access violation to be raised to alert you to the misuse. If there's no further use of the variable however in the current scope then setting to nil of course is redundant and serves no purpose. You should carefully review and ideally check your programs for memory leaks using for example the memory leak checking features of FastMM or some other tool. (There are several.) All that said, there are forms of automatic memory management available in Delphi on Windows: Interfaces support reference counting based memory management whereby the compiler will automatically free an interfaced object referenced via an interface reference when the enclosing method/function terminates, via code the compiler generates to check the reference count and act when it reaches zero. You should not manually free an interfaced object as this in turn may also cause an exception when the compiler auto-generated code also tries to free the object. This is a so-called "double-free" error. FastMM (or some other tool) can also be employed to help detect this type of mistake. Additionally please note that Embarcadero decided arguably somewhat controversially (in a departure from the behaviour on Windows) to adopt similar semantics for plain objects on the Delphi mobile compilers, this is commonly referred to as ARC ("Automatic Reference Counting", see here). So, when you write Delphi code and compile for a mobile target, then you do not need to explicitly call .Free() or even set to "nil" since the object will be automatically freed when its reference count hits zero. However, because of vaious reasons including not least the runtime cost of ARC and the conflicting semantics between the platforms, it looks like Embarcadero is now going to revert to making the mobile compilers behave the same as on Windows after Delphi 10.3 Rio, see here: http://blog.marcocantu.com/blog/2018-october-Delphi-ARC-directions.html I hope that helps. Edited March 5, 2019 by ByteJuggler Further Corrections and clarifications, added a link to ARC documentation on docwiki 1 1 Share this post Link to post
Ruslan 6 Posted March 5, 2019 (edited) 2 hours ago, ByteJuggler said: This means if you merely assign "nil" to an object reference, the memory pointed to originally by that reference is still allocated in the heap somewhere, but now "lost" -- you've caused a memory leak(!). I do not need to free the object, I use the variable as a iterator in a Dictionary or ObjectList, so the items in them do not need to be freed. I don't have problems o memory leaks, all the objects a freed where should be, I have just some messages in building the project. Please read again my question. Edited March 5, 2019 by Ruslan Share this post Link to post
ByteJuggler 45 Posted March 5, 2019 (edited) 32 minutes ago, Ruslan said: I do not need to free the object, I use the variable as a iterator in a Dictionary or ObjectList, so the items in them do not need to be freed. I don't have problems o memory leaks, all the objects a freed where should be, I have just some messages in building the project. Please read again my question. Yes, I was responding primarily to "TItem.Create" in your original post in context with the question "What is the right way of freeing the local class variables?". When applied in context of iterator then obviously the items belong somewhere else already etc. If your only concern is actually warnings about needlessly assigning nil then either don't do that or turn the warning off. (There's a way to disable most warning messages, I don't know off the top of my head whether and how to disable this particular message. Also some version of the Delphi compiler emitted as I recall some warnings or hints not entirely when you'd expect it. What version of Delphi are you using? If this is why you're seeing this, then ... ) Edited March 5, 2019 by ByteJuggler Share this post Link to post
David Heffernan 2353 Posted March 5, 2019 You said that the objects were instantiated by calling the constructor. You later say that they are loop variables used when iterating over a collection. So that's a total contradiction. So, with this new information the simple answer is that you never need to set the loop variable to nil. We read the question just fine. Please don't tell us to read it again. It's you that should read it again. Share this post Link to post
Ruslan 6 Posted March 6, 2019 19 hours ago, David Heffernan said: You said that the objects were instantiated by calling the constructor. You later say that they are loop variables used when iterating over a collection. These are just 2 ways of usage (in a constructor "OR" as iterator) as was written 22 hours ago, Ruslan said: (e.g. aItem := TItem.Create; or as iterations in Dictionary or ObjectLists) that is the answer I was expected for iterators 19 hours ago, David Heffernan said: you never need to set the loop variable to nil so I guess if a pointer is declared in a method that is used to fill a Dictionary, List or ObjectList than it is not needed to set it to nil at the end Share this post Link to post
David Heffernan 2353 Posted March 6, 2019 3 hours ago, Ruslan said: I guess if a pointer is declared in a method that is used to fill a Dictionary, List or ObjectList than it is not needed to set it to nil at the end You never need to set a pointer to nil. 1 Share this post Link to post