Note that there are some explanatory texts on larger screens.

plurals
  1. POMemory leak using WMI in Delphi 7
    primarykey
    data
    text
    <p>I'm experiencing a memory leak when using WMI from Delphi 7 to query a (remote) pc. The memory leak only occurs on Windows 2003 (and Windows XP 64). Windows 2000 is fine, and so is Windows 2008. I'm wondering if anyone has experienced a similar problem.</p> <p>The fact that the leak only occurs in certain versions of Windows implies that it might be a Windows issue, but I've been searching the web and haven't been able to locate a hotfix to resolve the issue. Also, it might be a Delphi issue, since a program with similar functionality in C# doesn't seem to have this leak. The latter fact has led me to believe that there might be another, better, way to get the information I need in Delphi without getting a memory leak.</p> <p>I've included the source to a small program to expose the memory leak below. If the line <code>sObject.Path_</code> below the <code>{ Leak! }</code> comment is executed, the memory leak occurs. If I comment it out, there's no leak. (Obviously, in the "real" program, I do something useful with the result of the <code>sObject.Path_</code> method call :).)</p> <p>With a little quick 'n dirty Windows Task Manager profiling on my machine, I found the following:</p> <pre> Before N=100 N=500 N=1000 With sObject.Path_ 3.7M 7.9M 18.2M 31.2M Without sObject.Path_ 3.7M 5.3M 5.4M 5.3M </pre> <p>I guess my question is: has anyone else encountered this problem? If so, is it indeed a Windows issue, and is there a hotfix? Or (more likely) is my Delphi code broken, and is there a better way to get the information I need?</p> <p>You'll notice on several occasions, <code>nil</code> is assigned to objects, contrary to the Delphi spirit... These are COM objects that do not inherit from <code>TObject</code>, and have no destructor I can call. By assigning <code>nil</code> to them, Windows's garbage collector cleans them up.</p> <pre><code>program ConsoleMemoryLeak; {$APPTYPE CONSOLE} uses Variants, ActiveX, WbemScripting_TLB; const N = 100; WMIQuery = 'SELECT * FROM Win32_Process'; Host = 'localhost'; { Must be empty when scanning localhost } Username = ''; Password = ''; 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_; sObject := nil; tempObj := Unassigned; end; Enum := nil; end; function ExecuteQuery: ISWbemObjectSet; var Locator: ISWbemLocator; Services: ISWbemServices; begin Locator := CoSWbemLocator.Create; Services := Locator.ConnectServer(Host, 'root\CIMV2', Username, Password, '', '', 0, nil); Result := Services.ExecQuery(WMIQuery, 'WQL', wbemFlagReturnImmediately and wbemFlagForwardOnly, nil); Services := nil; Locator := nil; end; procedure DoQuery; var ObjectSet: ISWbemObjectSet; begin CoInitialize(nil); ObjectSet := ExecuteQuery; ProcessObjectSet(ObjectSet); ObjectSet := nil; CoUninitialize; end; var i: Integer; begin WriteLn('Press Enter to start'); ReadLn; for i := 1 to N do DoQuery; WriteLn('Press Enter to end'); ReadLn; end. </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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