![]() |
Speicherfresser CreateProcess?
Guten Morgen!
Ich überarbeite gerade einen Dienst der in bestimmten Intervallen einen Prozess unter einem Benutzerkonto startet. Nun hab ich in meiner CreateProcess Methode ein Speicherleck, hab aber keine so rechte Ahnung wie genau ich damit umgehen muss. Hier mal der Code der Methode:
Delphi-Quellcode:
SNGetWorkingSetSize ist diese Methode:
procedure TMyDienst.CreateNewUserProcess(AUser, APassword, ADomain, AProgram : string);
var ltoken : Cardinal; LEnv : Pointer; pi : TProfileInfo; si : STARTUPINFO; pri : _PROCESS_INFORMATION; sil : TSecurityImpersonationLevel; LUser, LDomain, LPassword, LProgram : string; reg : TRegistry; begin try LUser:=AUser; LPassword:=APassword; LDomain:=ADomain; LProgram:=AProgram; snlogger.Log(Format('mem a: %d',[SNGetWorkingSetSize])); try FillChar(sil,SizeOf(TSecurityImpersonationLevel),#0); snlogger.Log(Format('mem b: %d',[SNGetWorkingSetSize])); sil := SecurityIdentification; snlogger.Log(Format('mem c: %d',[SNGetWorkingSetSize])); if LogonUser(PAnsiChar(LUser),PAnsiChar(LDomain),PAnsiChar(LPassword),LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,ltoken)then begin snlogger.Log(Format('mem d: %d',[SNGetWorkingSetSize])); if DuplicateTokenEx(ltoken,TOKEN_ALL_ACCESS,nil,sil,TokenPrimary,ltoken)then begin snlogger.Log(Format('mem e: %d',[SNGetWorkingSetSize])); fillchar(pi,sizeof(TProfileInfo),#0); pi.dwSize:=sizeof(TProfileInfo); pi.lpUserName:=PAnsiChar(LUser); if(LoadUserProfile(ltoken,pi))then begin snlogger.Log(Format('mem f: %d',[SNGetWorkingSetSize])); if (CreateEnvironmentBlock( lenv, ltoken, false ))then begin snlogger.Log(Format('mem g: %d',[SNGetWorkingSetSize])); FillChar(pri,sizeof(_PROCESS_INFORMATION),#0); ZeroMemory(@si,sizeof(si)); if not(CreateProcessAsUser( ltoken, nil, PAnsiChar(LProgram),//PChar(SN_PATH+SN_PROG+' -0000000 -q'), nil, nil, false, CREATE_UNICODE_ENVIRONMENT or CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS or CREATE_NO_WINDOW, //TODO: Priorität einstellen? lenv, nil, si, pri ))then SNLogger.Log('Prozess konnte nicht gestartet werden. '+SysErrorMessage(GetLastError),ltBoth); snlogger.Log(Format('mem h: %d',[SNGetWorkingSetSize])); if not DestroyEnvironmentBlock(lenv)then snlogger.Log('EnvironmentBlock konnte nicht geschlossen werden'); if not UnloadUserProfile(ltoken,pi.hProfile)then snlogger.Log('UserProfile konnte nicht geschlossen werden'); if not CloseHandle(pri.hProcess)then snlogger.Log('hProcess konnte nicht geschlossen werden'); if not CloseHandle(pri.hThread)then snlogger.Log('hThread konnte nicht geschlossen werden'); if not CloseHandle(ltoken)then snlogger.Log('ltoken konnte nicht geschlossen werden'); snlogger.Log(Format('mem i: %d',[SNGetWorkingSetSize])); //snlogger.log(inttostr(GetLastError)); end else SNLogger.Log('Arbeitsumgebung konnte nicht erstellt werden. '+SysErrorMessage(GetLastError)); end else SNLogger.Log('Benutzerprofil konnte nicht geladen werden. '+SysErrorMessage(GetLastError)); end else SNLogger.Log('Duplicate nicht möglich. '+SysErrorMessage(GetLastError)); end else SNLogger.Log('Login nicht möglich. '+SysErrorMessage(GetLastError),ltBoth); except on e : exception do SNLogger.Log('Fehler beim Starten eines Prozesses:'+e.Message+slinebreak+SysErrorMessage(GetLastError),ltBoth); end; finally snlogger.log(syserrormessage(getlasterror)); snlogger.Log(Format('mem j: %d',[SNGetWorkingSetSize])); end; end; ![]() Diese snlogger.log Methode schreibt mir den angegebenen String in ne Datei, da hab ich unter anderem folgendes: Zitat:
Das Problem eben ist, dass der Speicher nicht freigegeben wird und der Dienst irgendwann abstürzt. Das CreateEnvironmentBlock scheint hierbei am meisten Speicher zu fressen. Wenn ich das recht sehe, hab ich hier tokens und records, wie gebe ich die denn frei? Oder übersehe ich ein Objekt das ich nicht freigebe? Diese Suche anch Speicherlecks ist echt zermürbend :wall: |
Re: Speicherfresser CreateProcess?
Hi,
ich frage mich, warum immer das Working Set als Maßstab verwendet wird: Das Working Set ist abhängig von anderen Anwendungen auf dem System und laufenden Anwendungen im Vorder- und Hintergrund. (hier egal) Auch das Minimieren von Fenstern verändert das Working Set. So würde ich auf jeden Fall nicht nach Speicherlecks suchen. Spricht etwas dagegen mit FastMM4 im FullDebugMode anzufangen, und die enthaltenen Log-Funktion zu nutzen? Wenn das nicht hilft, kannst Du vor und nach kritischen Geschichten ein "ScanMemoryPoolForCorruptions" (so oder ähnlich, gerade kein Delphi an) von FastMM aufrufen. Nächster Schritt wäre für mich dann eine Kontrolle der Handles, z.B. mit Tools von SysInternals oder AQtime. Auch manche Exception Tracker sind hilfreich (madExcept, EurekaLog etc). Aber das Working Set bestimmt nicht... Gruß Assertor |
Re: Speicherfresser CreateProcess?
Danke für die Anwort.
FastMM4 hab ich bereits im FullDebugMode aktiv, liefert mir aber - seit ich einige Löcher gestopft hab - beim Beenden vom Dienst kein Logfile(mehr). Im Taskmanager sehe ich aber, dass der Speicherverbrauch immernoch steigt und steigt. Dieses ScanMemoryPoolForCorruptions werd ich mal testen, danke. Wenn ich damit auch nix finde schau ich mir noch die anderen Sachen an. Edit: Woah innerhalb von 5 Sekunden hab ich ne 11 mb große Datei durch das ScanMemoryPoolForCorruptions bekommen :shock: |
Re: Speicherfresser CreateProcess?
Zitat:
|
Re: Speicherfresser CreateProcess?
Also unter Vista hat die Spalte die Beschriftung "Arbeitsspeicher (privater Arbeitssatz)".
Unter XP schau ich bei "Speicherauslastung". Oder schau ich ander falschen Stelle? Edit: Ich werd mir das mal mit dem ProcessExplorer von sysinternals anschauen, da sieht man das etwas detaillierter |
Re: Speicherfresser CreateProcess?
Sorry für Doppelpost..
Also im ProcessExplorer seh ich beim Physical Memory, dass das Working Set Private immer weiter ansteigt. Das Working Set Shareable bleibt konstant. Beim Virtual Memory steigen die Private Bytes auch immer mehr. Hier hab ich auch Page Faults, die aber soweit ich weis nicht direkt was mit dem freigeben von Speicher zu tun haben. Edit: Kann ich denn irgendwie von den Speicherzahlen rausfinden um was genau es sich handelt, nicht freigegebene Objekte oder was anderes? Edit2: Laut Process Explorer steigt die Anzahl der Handles auch an, anfangs bei 180, sind es jetzt schon 220. |
Re: Speicherfresser CreateProcess?
Hallo,
hast du die Methode mal separat (neues, leeres Projekt) mit FastMM4 oder memcheck geprüft ? Heiko |
Re: Speicherfresser CreateProcess?
Hallo,
Delphi-Quellcode:
Wird hier nicht das Original-Token ltoken überschrieben ?
if DuplicateTokenEx(ltoken,TOKEN_ALL_ACCESS,nil,sil,TokenPrimary,ltoken)then
Mach doch mal sowas.
Delphi-Quellcode:
if DuplicateTokenEx(ltoken,TOKEN_ALL_ACCESS,nil,sil,TokenPrimary,ltoken2)then
Heiko |
Re: Speicherfresser CreateProcess?
hoika du bist ein Speichergott :firejump:
Das scheints gewesen zu sein :thumb: Jetz hab ich nur das Problem, dass ich ab und zu folgende Meldung bekomm: "Diese Sicherheitskennung kann nicht als Besitzer des Objekts zugeordnet werden" Das seltsame daran, er sagt er kann das CreateProcessAsUser ausführen, also das liefert ein true zurück, gestartet wurde allerdings nix, das GetLastError bringt dann die Meldung... Soll ich dafür en eigenen Thread aufmachen? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz