Entwickler-Ecke

Windows API - [WMI] Speicherauslastung erhöht sich ständig


Bergmann89 - Sa 23.02.08 15:37
Titel: [WMI] Speicherauslastung erhöht sich ständig
HI,

ich bin grad dabei n bisl mit WMI zu experimentieren, und da is mir aufgefallen, dass:
Wenn ich mit nem Timer immer wieder die Prozessorlast auslesen lasse, das jedesmal
die Speicherauslastung wächst! Das Prog war ca. ne halbe stunde an und hat 1000MB
Speicher benutz! Ich glaub das liegt daran, das die WMI-Prozedur immer wieder Variablen
erzeugt, aber nich wieder freigibt. Hab aber auch nix gefunden, wie ich das erledigen kann!


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
procedure TForm1.GetWMIstring (wmiHost, wmiClass, wmiProperty : string; var List: TStringList);
var Services: ISWbemServices;
var SObject:  ISWbemObject;
var ObjSet:   ISWbemObjectSet;
var SProp:    ISWbemProperty;
var Enum:     IEnumVariant;
var Value:    Cardinal;
var TempObj:  OleVariant;
var SN: string;
begin
  List.Clear;
  try
    Services :=  Locator.ConnectServer(wmiHost, 'root\cimv2', '', '', '','', 0, nil); //HIER
    ObjSet := Services.ExecQuery('SELECT * FROM '+wmiClass, 'WQL', wbemFlagReturnImmediately and wbemFlagForwardOnly , nil); //HIER
    Enum :=  (ObjSet._NewEnum) as IEnumVariant; //HIER
    while (Enum.Next(1, TempObj, Value) = S_OK) do
      begin
        SObject := IUnknown(tempObj) as ISWBemObject; //HIER
        SProp := SObject.Properties_.Item(wmiProperty, 0); //UND HIER
        if VarIsNull(SProp.Get_Value) then List.Add('')
        else
          begin
            SN := SProp.Get_Value;
            List.Add(SN);
          end;
      end;
  except 
    on exception do List.Add('');
  end;
end;


Weiß jemand ne lösung, wäre sehr dankbar!

____
MfG & Thx Bergmann


olliterski - Mo 25.02.08 10:24

Hallo,

also ich hab ehrlich gesagt noch nicht soviel damit rumexperimentiert und bin wahrscheinlich auch schon etwas raus, aber DIE Funktion rufst Du jedesmal über einen Timer auf?
Mit jedem Aufruf von 'Locator.ConnectServer(wmiHost, 'root\cimv2', '', '', '','', 0, nil);' erzeugst Du meines erachtens nach eine neue Instanz ohne die alte freizugeben!
Habe jedenfalls keine Zeile gefunden in der ein 'Disconnect' steht oder ein 'FREE'!

Viele Grüße

Oliver


Motzi - Mo 25.02.08 11:38

Die Referenzzähler von Interfaces werden von Delphi intern automatisch verwaltet, somit sollten alle Interfaces aus deiner Funktion freigegeben werden, sobald diese fertig ist.
Möglicherweise liegt das Problem woanders..?

Gruß, Motzi


Bernhard Geyer - Mo 25.02.08 18:39

user profile iconMotzi hat folgendes geschrieben:
Die Referenzzähler von Interfaces werden von Delphi intern automatisch verwaltet, somit sollten alle Interfaces aus deiner Funktion freigegeben werden, sobald diese fertig ist.
Möglicherweise liegt das Problem woanders..?

Vermutlich in schrottiger Implementierung auf MS-Seite. Ich habe z.B. im IE (TWebBrowser) schon oft erlebt das dieser einfach Objekte hinter Interfacezeigern nicht freigibt auch wenn auf Delphi-Seite alles OK ist. Mein Code ist deshalb mit ein paar _Releases ergänzt worden (für IE 7 ein paar) weniger um die Speicherlücken auf der "Gegenseite" zu beheben.


Bergmann89 - Mo 25.02.08 21:47

HI,

@olliterski:
hab ma n testproject geschrieben, in dem ist bloß
der timer und ne StringList/ListBox!

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  GetWMIString('','WIN32_Pocessor','Caption',StringList)
end;

Die Speicherauslastung steigt aber immer noch! Also liegt
das nich an mir/meinem Prog!

@Bernhard Geyer:
Was meinst du mit _Releases?! bzw wie geht das?
Wäre toll, wenn das mein Problem löst!

MfG Bergmann


Gahero - Mo 25.02.08 22:20

Genau das gleiche Problem habe ich auch. Es scheint aber an dieser Prozedur zu liegen, da es bei sämtlichen Aufrufen vorkommt...
Hatte das schonmal gepostet, vllt gibts ja jetzt enldich mal ne Lösung!


Delete - Mo 25.02.08 23:15

Mit WMI die CPUlast auszulesen ist nicht sehr sinnvoll, mach es besser mit adcpuusage:

http://www.delphi-forum.de/search.php?mode=results


olliterski - Di 26.02.08 21:36

user profile iconBergmann89 hat folgendes geschrieben:
HI,

@olliterski:
...Die Speicherauslastung steigt aber immer noch! Also liegt
das nich an mir/meinem Prog!



....doch es liegt an deinem Prog! Genauer gesagt am Zugriff auf WMI!
Google war wie immer mein Freund und mein Freund meinte IDEübergreifend, dass es sich schlichtweg um ein Memoryleak handelt! ;o)


QS07 - Do 28.02.08 21:12

HI,

hab das gleiche Problem, hab aber auch noch keine
Lösung gefunden! Wäre toll wenn da jmd ne idee hat!

MfG QS


Bernhard Geyer - Fr 29.02.08 22:20

user profile iconBergmann89 hat folgendes geschrieben:
@Bernhard Geyer:
Was meinst du mit _Releases?! bzw wie geht das?
Wäre toll, wenn das mein Problem löst!

Die fehlenden Freigaben werden wohl in der GetWMIstring-Implementierung sein.


Bergmann89 - Sa 01.03.08 16:36


Delphi-Quelltext
1:
2:
3:
4:
class function CoSWbemLocator.Create: ISWbemLocator;
begin
  Result := CreateComObject(CLASS_SWbemLocator) as ISWbemLocator;
end;


so wird das erzeugt, aber sowas wie DestroyComObj gibts eben nich, oder doch?!

MfG Bergmann.