Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I can reproduce the behaviour, the code leaks memory on Windows XP 64 and does not on Windows XP. Interestingly this occurs only if the <code>Path_</code> property is read, reading <code>Properties_</code> or <code>Security_</code> with the same code does not leak any memory. A Windows-version-specific problem in WMI looks like the most probable cause of this. My system is up-to-date AFAIK, so there probably isn't a hotfix for this either.</p> <p>I'd like to comment on your resetting all variant and interface variables, though. You write</p> <blockquote> <p>You'll notice on several occasions, nil is assigned to objects, contrary to the Delphi spirit... These are COM objects that do not inherit from TObject, and have no destructor I can call. By assigning nil to them, Windows's garbage collector cleans them up.</p> </blockquote> <p>This is not true, and consequently there is no need to set the variables to <code>nil</code> and <code>Unassigned</code>. Windows does not have a garbage collector, what you are dealing with are reference-counted objects, which are immediately destroyed once the reference count reaches 0. The Delphi compiler does insert the necessary calls to increment and decrement the reference count as necessary. Your assignments to <code>nil</code> and <code>Unassigned</code> decrement the reference count, and free the object when it reaches 0.</p> <p>A new assignment to a variable, or the exiting of the procedure take care of this as well, so additional assignments are (albeit not wrong) superfluous and decrease the clarity of the code. The following code is completely equivalent and does not leak any additional memory:</p> <pre><code>procedure ProcessObjectSet(WMIObjectSet: ISWbemObjectSet); var Enum: IEnumVariant; tempObj: OleVariant; Value: Cardinal; sObject: ISWbemObject; begin Enum := (wmiObjectSet._NewEnum) as IEnumVariant; while (Enum.Next(1, tempObj, Value) = S_OK) do begin sObject := IUnknown(tempObj) as SWBemObject; { Leak! } sObject.Path_; end; end; </code></pre> <p>I'd say one should explicitly reset interfaces only if this does actually free the object (so the current ref count has to be 1) and the destruction itself should really happen exactly at this point. Examples for the latter are that a large chunk of memory can be freed, or that a file needs to be closed or a synchronization object to be released.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload